Pact 是消费者驱动的契约测试工具,解决 C# 微服务中 Provider 接口变更导致 Consumer 反序列化失败、状态码不匹配等运行时错误,通过生成并验证 JSON 契约保障 API 协议一致性。
什么是 Pact 契约测试,它在 C# 里解决什么问题
Pact 是一种消费者驱动的契约测试(Consumer-Driven Contract Testing)工具,核心目标不是测接口功能是否正确,而是确保服务提供方(Provider)的 API 响应结构、状态码、字段类型、必选字段等,始终满足消费者(Consumer)代码中实际依赖的约定。C# 中用 Pact 主要防止“改了 Provider 接口但 Consumer 没同步更新”导致的运行时崩溃,比如 NullReferenceException 或反序列化失败。
常见错误现象包括:
- Consumer 升级后调用 Provider 报
JsonSerializationException(字段名变了、类型不匹配) - Provider 新增了非空字段,但 Consumer 的 DTO 没加对应属性,反序列化失败
- Provider 改了 HTTP 状态码(如 200 → 201),Consumer 的
EnsureSuccessStatusCode()报错
它不替代集成测试,也不验证业务逻辑;它是介于单元测试和端到端测试之间的一层“协议守门员”。
C# 中用 Pact.NET 写消费者测试的关键步骤
Pact 在 C# 生态主要靠 PactNet 库(支持 .NET Core 3.1+ 和 .NET 5+)。消费者测试本质是“模拟 Provider”,记录 Consumer 发出的请求与期望响应,生成一个 JSON 格式的契约文件(consumer-name-provider-name.json)。
实操要点:
- 安装 NuGet 包:
PactNet和PactNet.Windows(Windows)或PactNet.Linux(Linux/macOS) - 测试中不要直接调用真实 HTTP 接口,而是用
PactBuilder构建 Mock Server,把 Consumer 的 HTTP Client 指向它(例如通过HttpClient的BaseAddress) - 每个测试用例只描述一个交互(Interaction),必须显式调用
UponReceiving(...).WithRequest(...).WillRespondWith(...) - 测试末尾必须调用
VerifyInteractions(),否则契约不会写入磁盘 - 生成的契约文件默认放在
pacts/目录下,需提交进 Git,供 Provider 端验证使用
示例片段(简化):