api-contract-testing by secondsky/claude-skills
npx skills add https://github.com/secondsky/claude-skills --skill api-contract-testing验证 API 是否遵守消费者与提供者之间的契约,而无需进行完整的集成测试。
| 术语 | 定义 |
|---|---|
| 消费者 | 调用 API 的服务 |
| 提供者 | 暴露 API 的服务 |
| 契约 | 约定的请求/响应格式 |
| Pact | 消费者驱动的契约测试工具 |
| Schema | 结构定义(OpenAPI、JSON Schema) |
| Broker | 契约的中央存储库 |
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('john@example.com')
})
})
.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);
});
});
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
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();
const OpenApiValidator = require('express-openapi-validator');
app.use(OpenApiValidator.middleware({
apiSpec: './openapi.yaml',
validateRequests: true,
validateResponses: true,
validateSecurity: true
}));
建议:
不建议:
每周安装量
87
代码仓库
GitHub 星标数
93
首次出现
2026年1月23日
安全审计
安装于
claude-code72
gemini-cli68
codex68
opencode68
github-copilot66
cursor66
Verify that APIs honor their contracts between consumers and providers without requiring full integration tests.
| Term | Definition |
|---|---|
| Consumer | Service that calls an API |
| Provider | Service that exposes an API |
| Contract | Agreed request/response format |
| Pact | Consumer-driven contract testing tool |
| Schema | Structure definition (OpenAPI, JSON Schema) |
| Broker | Central repository for contracts |
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('john@example.com')
})
})
.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();
const OpenApiValidator = require('express-openapi-validator');
app.use(OpenApiValidator.middleware({
apiSpec: './openapi.yaml',
validateRequests: true,
validateResponses: true,
validateSecurity: true
}));
Do:
Don't:
Weekly Installs
87
Repository
GitHub Stars
93
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code72
gemini-cli68
codex68
opencode68
github-copilot66
cursor66
飞书视频会议CLI工具:lark-vc技能详解,高效搜索与管理会议记录与纪要
36,800 周安装
提示工程技能指南:安全构建、任务编排与LLM输出验证最佳实践
105 周安装
bloomery AI 编程教练教程 - 学习构建编码代理的引导式技能
105 周安装
Azure DevOps 自动化工具:工作项、代码仓库、流水线、制品全面集成指南
106 周安装
iOS/macOS应用发布前审查指南:资深开发者审计,避免App Store被拒
107 周安装
spec-product-prototype技能:基于PRD生成可交互原型说明文档,实现需求到设计的无缝衔接
107 周安装
CodeRecon代码侦察技能:深度架构分析与安全审计方法,快速理解陌生代码库
73 周安装