后端与接口
微服务 API 契约测试:用消费者驱动契约与 Schema…
在测试微服务通信、防止 API 破坏性变更或校验 OpenAPI 规范时,用契约测试确保消费者与提供者遵守约定。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
微服务 API 契约测试:用消费者驱动契特定
解决思路
- 使用消费者驱动契约、schema 验证和 Pact 等工具验证服务间 API 契约,确保消费者与提供者遵守约定,无需完整集成测试。
- Pact 消费者测试(TypeScript):从 '@pact-foundation/pact' 导入 PactV3、MatchersV3。
- Pact 消费者测试:创建 new PactV3({ consumer: 'OrderService', provider: 'UserService' })。
- Pact 消费者测试:用例 returns user by ID,使用 .given('user 123 exists').uponReceiving('a request for user 123').withRequest({ method: 'GET', path: '/users/123' }).willRespondWith({ status: 200, body: MatchersV3.like({ id: '123', name: MatchersV3.string('John'), email: MatchersV3.email('john@example.com') }) }).executeTest(async (mockServer) => { const response = await fetch(`${mockServer.url}/users/123`); expect(response.status).toBe(200); })。
- Pact 消费者测试:用例 returns 404 for non-existent user,使用 .given('user does not exist').uponReceiving('a request for non-existent user').withRequest({ method: 'GET', path: '/users/999' }).willRespondWith({ status: 404, body: MatchersV3.like({ error: { code: 'NOT_FOUND', message: MatchersV3.string() } }) }).executeTest(async (mockServer) => { const response = await fetch(`${mockServer.url}/users/999`); expect(response.status).toBe(404); })。
- Provider 验证:从 '@pact-foundation/pact' 导入 Verifier。
- Provider 验证:创建 new Verifier({ provider: 'UserService', providerBaseUrl: 'http://localhost:3000', pactBrokerUrl: process.env.PACT_BROKER_URL, publishVerificationResult: true, providerVersion: process.env.GIT_SHA, stateHandlers: { 'user 123 exists': async () => { await db.users.create({ id: '123', name: 'John' }); }, 'user does not exist': async () => { await db.users.deleteAll(); } } }).verifyProvider();。
- OpenAPI 验证(Express):const OpenApiValidator = require('express-openapi-validator');。
- OpenAPI 验证(Express):app.use(OpenApiValidator.middleware({ apiSpec: './openapi.yaml', validateRequests: true, validateResponses: true, validateSecurity: true }));。
- 其他实现:Python JSON Schema 参考 references/python-json-schema.md。
- 其他实现:Java REST Assured 参考 references/java-rest-assured.md。
- 其他实现:Pact Broker CI/CD 参考 references/pact-broker-cicd.md。
- Best Practices Do:从消费者视角测试。
- Best Practices Do:使用 matchers 进行灵活匹配。
- Best Practices Do:验证结构,而不是具体值。
- Best Practices Do:显式版本化契约。
- Best Practices Do:测试错误响应。
- Best Practices Do:在 CI 流水线中运行测试。
- Best Practices Do:测试向后兼容性。
- Best Practices Don't:不要在契约中测试业务逻辑。
- Best Practices Don't:不要硬编码具体值。
- Best Practices Don't:不要跳过错误场景。
- Best Practices Don't:不要忽略版本化。
- Best Practices Don't:不要在未验证的情况下部署。
- 工具:Pact 用于多语言消费者驱动契约。
- 工具:Spring Cloud Contract 用于 JVM 生态。
- 工具:OpenAPI/Swagger 用于 Schema-first 验证。
- 工具:Dredd 用于 API blueprint 测试。
- 工具:Spectral 用于 OpenAPI linting。
适用边界 · 注意事项
- 不适合仅验证业务逻辑;契约测试面向请求/响应结构与约定,业务逻辑应另测。
- 当无法在 CI 中运行消费者与提供者验证、或无法维护契约版本时,不适合依赖完整契约测试流程。
- 没有跨服务契约、只是单体内部调用或一次性手工接口调试时,不必引入 Pact/Pact Broker 等完整契约测试。