GH GambleHub

Mocking and stubs for integrations

1) Why do we need midges and plugs

Integrations with payment providers, KYC services, message brokers, CRM, etc. make tests slow, unstable and expensive. Moki/plugs allow:
  • Isolate service logic from an unstable environment
  • Determine responses and errors
  • reproduce rare border cases (timeouts, 429/5xx, inconsistency);
  • run tests locally and in CI quickly and predictably.
💡 Principle: the lower the test level (Unit/Component), the more we replace; the closer to the production reality (Integration/E2E), the fewer plugs.

2) Terms and taxonomy

Stub is a simple stub with a fixed response, without interaction checks.
Mock - an object that waits for calls and verifies them (order/number/arguments).
Fake is a simplified implementation (for example, an In-Memory repository) with real behavior.
Spy is a wrapper that records actual calls.
Service Virtualization is a "virtual" external service with scripts, status and network features.
Record/Replay - recording of real traffic and subsequent playback (with filters/edition).

When to choose:
SituationTool
Pure business logicFakes (in-memory), unit-mocks
HTTP integration with simple casesStubs (WireMock/MockServer/HTTPServer)
Check customer contract to providerCDC mocks (Pact)
Complex Network Scenarios/Conditions/ErrorsService virtualization / Hoverfly / MockServer
Messages (Kafka/RabbitMQ)Testcontainers + schema-aware producer/consumer stubs

3) Architectural patterns for testability

Ports & Adapters (Hexagonal): take the integration beyond the interfaces - it is easy to replace it with fake/mock.
Anti-corruption layer (ACL): one module translates an external model into a domain model - fewer moka points.
Contract-aware clients: OpenAPI/Protobuf generation → fewer manual inconsistencies.
Feature flags and sandbox modes: secure keys/endpoints for the provider's stable.

4) HTTP: tools and examples

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 (with body check and variations):
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 (Dynamics/Verifications)

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)

Record the traffic against the provider's sandbox, clear the PII, fix it as fixture.
In simulate mode, add variations: 200/4xx/5xx, delays and "flaky" windows.

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 Stab generation

Generate a server by '.proto', implement methods with controlled responses.
Check metadata (headers), statuses ('codes. InvalidArgument`, `codes. DeadlineExceeded`).

Go gRPC fake (snippet):
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 for negatives


grpcurl -plaintext -d '{"amount":0}' localhost:50051 payouts. Payouts/Create

6) Posts and streams: Kafka/RabbitMQ

6. 1 Schema-aware moki

Use Schema Registry and validate Avro/JSON-Schema/Protobuf in tests.
Producer test: the message corresponds to the schema; Consumer test: accepts old and new versions.

6. 2 Testcontainers (Kafka + Registry example)

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 Negatives

Duplicates, rearrangement of order, delivery delay, "poisonous" messages (dead-letter).
Large messages (near-limit), unrecognized schema versions.

7) Contract-aware plugs

7. 1 Pact (CDC mocks)

Consumer generates expectations → pact file → provider verifies on the stand.
Pact stub server plays expectations for client integration tests.

7. 2 OpenAPI/Protobuf → stable generation

Tools that raise the mock server from the specification (including Prism, openapi-mock, grpc-mock).
Include negative examples/codes in the specification: this is also a contract.

8) Network and chaos: simulation of failures

Delays and jitter: fixed/distributed; check deadlines and per-try timeout.
Timeouts/breaks: half-open connections, RST, reset stream H2, 503/Retry-After.
Packet loss/duplicate: for gRPC/streams.
Tools: Toxiproxy, MockServer (fault injection), xk6-disruptor, netem in CI.

Example of Toxiproxy (CLI):

toxiproxy-cli toxic add psp --type latency --latency 300 --jitter 100

9) Data, secrets and determinism

Redact and synthetics: no PII in fixes; money - decimal/strict formatting.
Time fixation: fake clock; "yesterday/today" - control.
Idempotency: same'Idempotency-Key '→ same response.
Generators: factories/builders of data with transparent values (e. g., `test_user_001`).
Versioning fixes (tags), do not store "removed" answers without mediation.

10) CI/CD and environments

Matrix: unit (in-process fakes) → component (local virtualization) → integration (minimum moks, Testcontainers).
Artifacts: pact files, OpenAPI snapshots, ioc server logs, PCAP for drops.
Parallelism: unique ports/key prefixes; insulation of containers.
Gate: contract green (CDC verify), specification valid (lint), negatives passed.

11) Antipatterns

Moki "copy" defects in real service → false confidence. Treated with contracts and periodic record/verify.
The "macromocks" of the whole world in every test → fragility, expensive mainstream. Make thin ports and ACLs.
Moki in E2E where real integration is needed (especially payments/webhooks with HMAC/mTLS).
Flakes due to time/random/network racing → use fake clock, deterministic seats.
Secrets in fixes/repositories. Secrets - only through secret storage CI.

12) Specifics of iGaming/Finance

Payments/withdrawals: Mokes must support 'Idempotency-Key', 'Retry-After', HMAC/mTLS, sanction codes and 'long' responses.
Bonus logic/anti-fraud: velocity/429 scenarios, ATO/challenge, risk solutions' allow/deny/challenge'with TTL.
KYC/AML: sandbox responses by KYC levels, negatives (mismatch, invalid documents), webhooks with anti-replay ('X-Timestamp' window).
Jurisdictions/Tenants: Required 'X-Tenant/X-Region' headings, different response profiles.

13) Mini recipes (cheat sheet)

Repeat payment: WireMock "Scenarios" - first '201', second '409 duplicate'.
Slow PSP: MockServer 'responseDelay' + checking per-try timeout on client.
Webhooks: local HTTP server + HMAC signature verification; replay after 5 seconds does not create a double.
Kafka duplicates: post the same message twice; handler must be idempotent.
gRPC statuses: matrix of 'codes' tests (InvalidArgument, DeadlineExceeded, ResourceExhausted).

14) Prod Readiness Checklist

  • Ports/adapters are highlighted; integrations are hidden behind interfaces.
  • For HTTP/gRPC - there are contract-aware stabs (Pact/OpenAPI/Proto) with negatives.
  • For brokers - Testcontainers + Registry; duplicate/order/large message tests.
  • Chaos: delays, timeouts, reset, 429/503 with 'Retry-After'; the network is emulated (Toxiproxy/netem).
  • Fixtures without PII; fake clock; idempotency is minted.
  • CI matrix: unit → component → integration; log/contract artifacts are preserved.
  • Provider sandboxes: keys are separated, endpoints are configured, there is a runbook.
  • Record/Replay is updated on schedule, traces are edited.
  • flaky metrics and test durations under control; alerts at growth.

15) TL; DR

Isolate integrations through thin ports and use the right tool for the task: stubs for simple cases, mocks for verification of interactions, fakes for realistic behavior, service virtualization and chaos for network and rare errors. Make the moki contract-conscious (Pact/OpenAPI/Proto), keep the fixes deterministic and PII-free, simulate delays/timeouts/429/5xx. In CI, build a pyramid: unit → component → integration; release block with red contracts. For payment/CCM paths, consider HMAC/mTLS, idempotence and negative scenarios.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.