目标
靠“把所有服务部署到一起”来验证集成,又慢又脆,而且只能在合并后发现破裂。消费者契约在各自服务的 CI 内、用几秒钟验证同一个事实——提供方仍然满足消费方的期望——并在任何人合并之前拦住破坏。
步骤要点
- 选最痛的集合作试点:从引发事故最多的服务对开始,而不是最简单的那对,程序必须先在真实痛点上证明价值,两个团队都要同意。
- 消费方先写契约:把依赖的交互(请求形态、响应字段、状态语义)定义为可执行的契约测试,失败的测试就是期望声明,契约发布到 broker。
- 提供方对照验证:提供方 CI 拉取已发布契约并在运行实例上重放,任何分歧都让构建失败在合并之前。
- 退役等价的端到端测试:契约覆盖该交互后,删除需要两个服务同时部署的对应 E2E 用例,流水线时长可见下降。
- 一对一对循环扩展:对下一个集成重复“定义—发布—验证—退役”,每次控制在一周内完成。
排错提示
契约越写越多 E2E 一条没删是只加不减,每覆盖一个交互就删对应的多服务用例;试点挑了最简单的对说服不了任何人,用事故史选最痛的,第一次拦截就是最好的广告;提供方 CI 没拉契约等于只有一半流程,broker 的 webhook 要真接进流水线。
适用边界
契约测试验证接口兼容性而非业务语义正确性,关键链路仍需少量端到端冒烟;契约维护成本随消费者数量增长,接口设计要有版本纪律配合。
代码示例
pair: web (consumer) -> orders-api (provider)
consumer: web
contract: GET /orders/{id} -> 200 {id, total_cents, status}
test: expects total_cents > 0 for fixture order
-> publishes contract v3 to broker
provider: orders-api CI
fetches web@v3 contract
replays against running instance:
GET /orders/demo-1 -> 200 {total_cents: -5} FAIL
build blocked BEFORE merge
retired: e2e_checkout_full (needed web+orders+db+cache)
pipeline: 41 min -> 27 min