关于 api-contract-testing
用于验证 API 是否符合消费者与提供方约定的测试技能,涵盖 Pact 消费者驱动测试、提供方验证和 OpenAPI 模式校验。
主要功能
- 01消费者驱动的 Pact 测试
- 02提供方验证
- 03OpenAPI 请求与响应校验
- 04多种语言生态的实践指南
适用场景
- 01检查依赖服务间的 API 约定
- 02根据已发布契约验证提供方行为
- 03按 OpenAPI 校验 Express 请求与响应
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill api-contract-testing安装后在 Claude Code 中输入/api-contract-testing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/java-rest-assured.mdpact-broker-cicd.mdpython-json-schema.md详细介绍
API 契约测试
验证 API 是否遵守消费者与提供者之间的契约,无需进行完整的集成测试。
核心概念
| 术语 | 定义 |
|---|---|
| 消费者 | 调用 API 的服务 |
| 提供者 | 提供 API 的服务 |
| 契约 | 双方约定的请求/响应格式 |
| Pact | 消费者驱动的契约测试工具 |
| 架构 | 结构定义(OpenAPI、JSON Schema) |
| Broker | 契约的中央存储库 |
Pact 消费者测试(TypeScript)
import { PactV3, MatchersV3 } from '@pact-foundation/pact';
const provider = new PactV3({
consumer: 'OrderService',
provider: 'UserService'
});
describe('User API Contract', () => {
it('returns user by ID', async () => {
await provider
.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('[email protected]')
})
})
.executeTest(async (mockServer) => {
const response = await fetch(`${mockServer.url}/users/123`);
expect(response.status).toBe(200);
});
});
it('returns 404 for non-existent user', async () => {
await provider
.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);
});
});
});
提供者验证
import { Verifier } from '@pact-foundation/pact';
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');
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
最佳实践
应该:
- 从消费者的角度进行测试
- 使用匹配器实现灵活匹配
- 验证结构,而非特定值
- 明确对契约进行版本控制
- 测试错误响应
- 在 CI 流水线中运行测试
- 测试向后兼容性
不应该:
- 在契约中测试业务逻辑
- 对特定值进行硬编码
- 跳过错误场景
- 忽略版本控制
- 未经验证就部署
工具
- Pact - 多语言消费者驱动契约
- Spring Cloud Contract - JVM 生态系统
- OpenAPI/Swagger - 以架构为先的验证
- Dredd - API Blueprint 测试
- Spectral - OpenAPI lint 工具
评论
支持 Markdown