Mocking und Stubs für Integrationen
1) Warum Sie Moks und Stecker brauchen
Integrationen mit Zahlungsanbietern, KYC-Diensten, Message Brokern, CRMs usw. machen Tests langsam, instabil und teuer. Moki/Stecker ermöglichen:- die Dienstlogik von der instabilen Umgebung zu isolieren;
- Determinieren von Antworten und Fehlern;
- seltene Grenzfälle reproduzieren (Timeouts, 429/5xx, Nichtkonsistenz);
- Führen Sie Tests lokal und in CI schnell und vorhersehbar durch.
2) Begriffe und Taxonomie
Stub ist ein einfacher Stub mit einer festen Antwort, ohne Interaktionsprüfungen.
Mock ist ein Objekt, das auf Aufrufe wartet und diese verifiziert (Reihenfolge/Anzahl/Argumente).
Fake ist eine vereinfachte Implementierung (z.B. In-Memory-Repository) mit realem Verhalten.
Spy ist ein Wrapper, der tatsächliche Anrufe aufzeichnet.
Service Virtualization ist ein „virtueller“ externer Service mit Szenarien, Status und Netzwerkmerkmalen.
Record/Replay - Aufnahme des realen Verkehrs und anschließende Wiedergabe (mit Filtern/Redaktion).
3) Architektonische Muster für Testbarkeit
Ports & Adapters (Hexagonal): Nehmen Sie die Integration hinter die Schnittstellen - einfach durch Fake/Mock zu ersetzen.
Anti-Corruption Layer (ACL): Ein Modul übersetzt ein externes Modell in ein Domain-Modell - weniger Mokka-Punkte.
Contract-aware Clients: Die Generierung über OpenAPI/Protobuf → weniger manuelle Inkonsistenzen.
Feature-Flags und Sandbox-Modi: Sichere Schlüssel/Endpunkte für den Provider-Riegel.
4) HTTP: Tools und Beispiele
4. 1 WireMock (standalone/Java DSL)
JSON-stab:json
{
"request": { "method": "POST", "urlPath": "/v1/payouts", "headers": { "Idempotency-Key": { "matches": ".+" } } },
"response": {
"status": 201,
"headers": { "Content-Type": "application/json" },
"jsonBody": { "id": "po_123", "status": "queued" },
"fixedDelayMilliseconds": 80
}
}
Java DSL (mit Body Check und Variationen):
java stubFor(post(urlEqualTo("/v1/payouts"))
.withHeader("Idempotency-Key", matching(".+"))
.withRequestBody(matchingJsonPath("$.amount", equalTo("100. 00")))
.willReturn(aResponse(). withStatus(201). withHeader("Content-Type","application/json")
.withBody("{\"id\":\"po_123\",\"status\":\"queued\"}")));
4. 2 MockServer (Dynamik/Verifikation)
json
{
"httpRequest": { "method": "GET", "path": "/v1/wallets/w123" },
"httpResponse": { "statusCode": 200, "headers":[{"name":"Content-Type","values":["application/json"]}],
"body": { "id":"w123","currency":"EUR","balance":0 } }
}
4. 3 Hoverfly (middleware, record/replay)
Notieren Sie den Verkehr gegen die „Sandbox“ des Anbieters, löschen Sie die PII, fixieren Sie als Fixture.
Fügen Sie im Simulate-Modus Variationen hinzu: 200/4xx/5xx, Verzögerungen und „flaky“ Fenster.
4. 4 Node (Nock) / Python (responses) / Go (`httptest`)
Nock:js nock('https://psp. example. com')
.post('/v1/payouts'). reply(201, { id:'po_123', status:'queued' })
.post('/v1/payouts'). reply (409, {code: 'duplicate'}) ;//second call - conflict
Go:
go srv:= httptest. NewServer(http. HandlerFunc(func(w http. ResponseWriter, r http. Request){
if r. Header. Get("Idempotency-Key") == "" { w. WriteHeader(400); return }
w. Header(). Set("Content-Type","application/json")
w. WriteHeader(201); w. Write([]byte(`{"id":"po_123","status":"queued"}`))
}))
defer srv. Close()
5) gRPC/Protobuf
5. 1 Erzeugung eines Stabes
Generieren Sie einen Server durch '.proto', implementieren Sie Methoden mit kontrollierten Antworten.
Überprüfen Sie die Metadaten (Header), Status ('Codes. InvalidArgument`, `codes. DeadlineExceeded`).
go type FakePayouts struct{ pb. UnimplementedPayoutsServer }
func (f FakePayouts) Create(ctx context. Context, in pb. PayoutReq)(pb. PayoutRes,error){
if in. Amount <= 0 { return nil, status. Error(codes. InvalidArgument,"amount>0") }
return &pb. PayoutRes{Id:"po_123", Status:"QUEUED"}, nil
}
5. 2 grpcurl für Negative
grpcurl -plaintext -d '{"amount":0}' localhost:50051 payouts. Payouts/Create
6) Nachrichten und Streams: Kafka/RabbitMQ
6. 1 Schema-aware moki
Verwenden Sie Schema Registry und validieren Sie Avro/JSON-Schema/Protobuf in Tests.
Produzententest: die Nachricht entspricht dem Schema; Consumer-Test: Akzeptiert alte und neue Versionen.
6. 2 Testcontainer (Beispiel Kafka + Registry)
java
KafkaContainer kafka = new KafkaContainer(DockerImageName. parse("confluentinc/cp-kafka:7. 6. 1"));
kafka. start();
//We publish the event and wait for consumption with deduplication by key
6. 3 Negative
Duplikate, Neuordnung der Reihenfolge, Lieferverzögerung, „giftige“ Nachrichten (Dead-Letter).
Große Nachrichten (near-limit), unerkannte Versionen von Schemata.
7) Vertrag-aware Stecker
7. 1 Pact (CDC mocks)
Consumer bildet Erwartungen → Pact-Datei → Provider verifiziert am Stand.
Pact stub server reproduziert die Erwartungen für Client-Integrationstests.
7. 2 OpenAPI/Protobuf → Stabgenerierung
Tools, die den Mock-Server aus der Spezifikation heben (einschließlich Prism, openapi-mock, grpc-mock).
Fügen Sie negative Beispiele/Codes in die Spezifikation ein: Dies ist auch ein Vertrag.
8) Netzwerk und Chaos: Fehlersimulation
Verzögerungen und Jitter: fest/verteilt; Überprüfen Sie die Fristen und per-try Timeout.
Zeitüberschreitungen/Unterbrechungen: halb-offene Verbindungen, RST, H2-Stream zurücksetzen, 503/Retry-After.
Paketverluste/Duplikate: für gRPC/Streams.
Werkzeuge: Toxiproxy, MockServer (Fault Injection), xk6-disruptor, netem im CI.
toxiproxy-cli toxic add psp --type latency --latency 300 --jitter 100
9) Daten, Geheimnisse und Determinismus
Redact und Synthetik: kein PII in Fixstrukturen; Geld - decimal/strenge Formatierung.
Zeiterfassung: Fake-Uhr; „gestern/heute“ - kontrollieren.
Idempotency: Derselbe „Idempotency-Key“ → dieselbe Antwort.
Generatoren: Datenfabriken/-bildner mit transparenten Werten (e. g., `test_user_001`).
Versionieren Sie Fixturen (Tags), speichern Sie keine „gefilmten“ Antworten ohne Mediation.
10) CI/CD und Umgebungen
Matrix: Einheit (in-process fakes) → Komponente (lokale Virtualisierung) → Integration (Minimum Mocks, Testcontainer).
Artefakte: Pact-Dateien, OpenAPI-Snapshots, Mock-Server-Logs, PCAP bei Stürzen.
Parallelität: eindeutige Ports/Schlüsselpräfixe; Isolierung von Containern.
Gate: Vertragsgrün (CDC verify), Spezifikation gültig (lint), Negative bestanden.
11) Antipatterns
Moki „kopieren“ die Mängel des realen Dienstes → das falsche Vertrauen. Behandelt mit Verträgen und periodischen record/verify.
Die „Makromoks“ einer ganzen Welt in jedem Test → Zerbrechlichkeit, lieber Maintenance. Machen Sie dünne Ports und ACLs.
Moki in E2E, in denen eine echte Integration erforderlich ist (insbesondere Zahlungen/Webhooks mit HMAC/mTLS).
Flakes aufgrund von Zeit/random/Netzwerk-Rennen → verwenden Sie gefälschte Uhr, deterministische sids.
Geheimnisse in Fiktionen/Repository. Geheimnisse gibt es nur durch CI Secret Storage.
12) Spezifität von iGaming/Finanzen
Zahlungen/Schlussfolgerungen: Moks sollten „Idempotency-Key“, „Retry-After“, HMAC/mTLS, Sanktionscodes und „lange“ Antworten unterstützen.
Bonus-Logik/Fraud: Velocity/429-Szenarien, ATO/Challenge, Risikolösungen 'allow/deny/challenge' mit TTL.
KYC/AML: Sandbox-Antworten nach KYC-Level, Negative (Mismatch, ungültige Dokumente), Webhooks mit Anti-Replay ('X-Timestamp' -Fenster).
Gerichtsbarkeiten/Tenanten: obligatorische Überschriften „X-Tenant/X-Region“, unterschiedliche Antwortprofile.
13) Mini-Rezepte (Spickzettel)
Zahlungs-Wiederholung: WireMock „Scenarios“ ist das erste' 201', das zweite' 409 duplicate'.
Slow PSP: MockServer 'responseDelay' + Überprüfung der Per-Try-Timeout im Client.
Webhooks: lokaler HTTP-Server + Überprüfung der HMAC-Signatur; Wiederholung nach 5 Sekunden erzeugt kein Doppel.
Kafka-Duplikate: Veröffentlichen Sie dieselbe Nachricht zweimal; Der Händler muss idempotent sein.
gRPC-Status: Matrix von Tests nach 'codes' (InvalidArgument, DeadlineExceeded, ResourceExhausted).
14) Checkliste Prod-Ready
- Ports/Adapter sind hervorgehoben; Integrationen hinter Schnittstellen versteckt.
- Für HTTP/gRPC - es gibt contract-aware Stacks (Pact/OpenAPI/Proto) mit Negativen.
- Für Broker - Testcontainers + Registry; Tests für Duplikate/Reihenfolge/große Nachrichten.
- Chaos: Delays, Timeouts, Reset, 429/503 mit „Retry-After“; Netzwerk wird emuliert (Toxiproxy/netem).
- Fixturen ohne PII; fake clock; Idempotenz wird gejagt.
CI-Matrix: Einheit → Komponente → Integration Log-/Vertragsartefakte werden gespeichert.
- Anbieter-Sandboxen: Schlüssel werden getrennt, Endpunkte konfiguriert, es gibt ein Runbook.
- Record/Replay wird planmäßig aktualisiert, die Traces werden bearbeitet.
- Metriken flaky und Dauer der Tests unter Kontrolle; Alert beim Wachstum.
15) TL; DR
Isolieren Sie Integrationen über dünne Ports und nutzen Sie das passende Werkzeug unter der Aufgabe: Stubs für einfache Fälle, Mocks für Verifikation von Interaktionen, Fakes für realistisches Verhalten, Service-Virtualisierung und Chaos - für vernetzte und seltene Fehler. Machen Sie moki vertragsbewusst (Pact/OpenAPI/Proto), halten Sie die Fixturen deterministisch und ohne PII, simulieren Sie Verzögerungen/Timeouts/429/5xx. Bauen Sie in CI eine Pyramide: Einheit → Komponente → Integration; Freigabe bei roten Verträgen sperren. Berücksichtigen Sie bei Zahlungs-/CUS-Pfaden HMAC/mTLS, Idempotenz und negative Szenarien.