GH GambleHub

用于集成的Mocking和stubs

1)为什么需要清洗和存根

与支付提供商,KYC服务,消息经纪人,CRM等的集成使测试缓慢,不稳定且昂贵。清洗/存根允许:
  • 将服务逻辑与不稳定的环境隔离开来;
  • 确定答桉和错误;
  • 重现罕见的边界案例(taymauts,429/5xx,非约束性);
  • 在本地和CI中快速、可预测地运行测试。
💡 原理:测试级别(单位/组件)越低,替换越多;越接近原生现实(Integration/E2E),插头越少。

2)术语和分类法

Stub是一个简单的固定响应存根,没有交互检查。
Mock是等待呼叫并对其进行验证的对象(顺序/数量/参数)。
Fake是具有真实行为的简化实现(例如In-Memory存储库)。
Spy是记录实际呼叫的包装纸。
服务虚拟化是一种具有脚本,状态和网络功能的"虚拟"外部服务。
Record/Replay-记录真实流量并随后播放(带过滤器/编辑)。

什么时候选择:
三.情况工具
纯粹的商业逻辑Fakes (in-memory), unit-mocks
与简单桉例的HTTP集成Stubs (WireMock/MockServer/HTTPServer)
验证客户与提供商的合同CDC mocks (Pact)
复杂的脚本/状态/网络错误Service virtualization / Hoverfly / MockServer
消息(Kafka/RabbitMQ)Testcontainers+schema-aware生产商/消费者stubs

3)可测试性的建筑模式

端口和适配器(Hexagonal):提供接口集成-易于替换为fake/mock。
反腐败层(ACL):一个模块将外部模型转换为域-少于mok点。
客户端:通过OpenAPI/Protobuf生成→减少手动不匹配。
功能标志和sandbox模式:提供商稳定性的安全密钥/端点。

4)HTTP: 工具和示例

4.1 WireMock (standalone/Java DSL)

JSON-I:
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(具有身体检查和变化):
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(扬声器/验证)

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)

记录与提供商"沙箱"的流量,清除PII,记录为固定。
在模拟模式下,添加变体:200/4xx/5xx、延迟和"flaky"窗口。

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 Staba生成

通过".proto"生成服务器,实现受控响应的方法。

检查元数据(headers)、状态('codes.InvalidArgument`, `codes.DeadlineExceeded`).

Go gRPC fake(片段):
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用于底片


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

6)消息和流: Kafka/RabbitMQ

6.1 Schema-aware洗衣机

使用Schema Registry并在测试中验证Avro/JSON-Schema/Protobuf。
生产者测试:消息符合模式;消费者测试:接受新旧版本。

6.2 Testcontainers(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负片

复制,顺序排列,延迟交付,"有毒"消息(死信)。
大消息(近极限),未知版本的电路。

7) Contract-aware存根

7.1 Pact (CDC mocks)

消费者形成期望→ pact文件→提供者在展位上验证。
Pact stub Server播放客户端集成测试的期望值。

7.2 OpenAPI/Protobuf → Stabes生成

使莫克服务器脱离规范的工具(例如:Prism,openapi-mock,grpc-mock)。
在规范中包含负面的示例/代码:这也是合同。

8)网络与混乱: 故障模拟

延迟和挤压:固定/分布;检查截止日期和工作时间。
Taymauts/断裂:半开放连接,RST,H2流重置,503/Retry-After。
批量丢失/重复:适用于gRPC/流。
工具:Toxiproxy, MockServer (fault injection), xk6-disruptor, netem in CI。

Toxiproxy(CLI)示例:

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

9)数据、秘密和决定论

Redact和合成剂:虚构中没有PII;金钱-decimal/严格的格式。
时间固定:假时钟;"昨天/今天"-控制。
相同性:相同的"Idempotency-Key" →相同的答案。

生成器: 具有透明值(e.g., `test_user_001`).

转化虚拟文件(标签),不要在没有中介的情况下存储"删除"的答桉。

10)CI/CD和环境

矩阵:单位(流程错误)→组件(本地虚拟化)→整合(最低限度moks,Testcontainers)。
工件:pact文件、OpenAPI snapshots、moc服务器日志、PCAP。
并发:唯一的端口/密钥前缀;容器隔离。
门:合同绿色(CDC验证),规范验证值(lint),底片通过。

11)反模式

Moks"复制"了实际服务的缺陷→虚假的信心。接受合同和定期记录/验证的治疗。
整个世界的"Macromoki"在每次测试中都→脆弱性,昂贵的主流。完成薄端口和ACL。
洗涤到需要真正集成的E2E(尤其是使用HMAC/mTLS 的支付/webhooks)。
由于时间/随机/网络比赛而产生的长笛→使用假时钟,确定性座位。
虚构/存储库中的秘密。秘密-仅通过CI秘密存储。

12) iGaming/财务细节

付款/结论:洗涤应支持"Idempotency-Key","Retry-After",HMAC/mTLS,制裁代码和"长期"响应。
Bonus Logic/antifrod:velocity/429脚本,ATO/挑战,TTL的"allow/deny/challenge"风险解决方案。
KYC/AML:对KYC级别,否定词(mismatch,无效文档),带有反重播的webhooks("X-Timestamp"窗口)的sandbox响应。
司法管辖区/特南特:强制性标题"X-Tenant/X-Region",不同的响应配置文件。

13)迷你食谱(spargalka)

重复付款:WireMock "Scenarios"是第一个"201",第二个是"409 duplicate"。
慢速PSP: MockServer的"响应延迟"+检查客户端中的工作时间。
Webhooks:本地HTTP服务器+HMAC签名验证;5秒后的重播不会产生双打。
Kafka副本:两次发布同一消息;亨德勒必须保持相等。
gRPC状态:通过"代码"进行矩阵测试(InvalidArgument,DeadlineExceeded,ResourceExhausted)。

14)准备就绪支票清单

  • 分配端口/适配器;集成隐藏在接口后面。
  • 对于HTTP/gRPC-存在带有底片的contract-aware stables (Pact/OpenAPI/Proto)。
  • 对于经纪人-Testcontainers+Registry;重复/顺序/大消息测试。
  • 溷乱:延误、停顿、重置,429/503 with "Retry-After";网络被模拟(Toxiproxy/netem)。
  • 没有PII的Fixtura;fake clock;偶然性。
  • CI矩阵:单位→组件→整合;文物/合同保存。
  • 提供商的沙箱:密钥是分离的,后端是配置的,有运行簿。
  • Record/Replay会按计划更新,信托会编辑。
  • 控制下测试的flaky和持续时间的度量;生长时的异常。

15) TL;DR

通过薄端口隔离集成,并使用正确的工具执行任务:用于简单桉例的堆栈、用于验证交互的堆栈、用于现实行为的堆栈、用于网络和罕见错误的服务虚拟化和chaos。使洗涤合约(Pact/OpenAPI/Proto),保持假象确定性和没有PII, 模拟延迟/taymauts/429/5xx。在CI中构建金字塔:单位→组件→集成;以红色合同阻止发布。对于支付/KUS路径,请考虑HMAC/mTLS,等效性和负面情况。

Contact

联系我们

如需任何咨询或支持,请随时联系我们。我们随时准备提供帮助!

开始集成

Email — 必填。Telegram 或 WhatsApp — 可选

您的姓名 可选
Email 可选
主题 可选
消息内容 可选
Telegram 可选
@
如果填写 Telegram,我们也会在 Telegram 回复您。
WhatsApp 可选
格式:+国家代码 + 号码(例如:+86XXXXXXXXX)。

点击按钮即表示您同意数据处理。