api-contract-testing
Scannednpx machina-cli add skill secondsky/claude-skills/api-contract-testing --openclawFiles (1)
SKILL.md
3.8 KB
API Contract Testing
Verify that APIs honor their contracts between consumers and providers without requiring full integration tests.
Key Concepts
| 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 |
Pact Consumer Test (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('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);
});
});
});
Provider Verification
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 Validation (Express)
const OpenApiValidator = require('express-openapi-validator');
app.use(OpenApiValidator.middleware({
apiSpec: './openapi.yaml',
validateRequests: true,
validateResponses: true,
validateSecurity: true
}));
Additional Implementations
- Python JSON Schema: See references/python-json-schema.md
- Java REST Assured: See references/java-rest-assured.md
- Pact Broker CI/CD: See references/pact-broker-cicd.md
Best Practices
Do:
- Test from consumer perspective
- Use matchers for flexible matching
- Validate structure, not specific values
- Version contracts explicitly
- Test error responses
- Run tests in CI pipeline
- Test backward compatibility
Don't:
- Test business logic in contracts
- Hard-code specific values
- Skip error scenarios
- Ignore versioning
- Deploy without verification
Tools
- Pact - Multi-language consumer-driven contracts
- Spring Cloud Contract - JVM ecosystem
- OpenAPI/Swagger - Schema-first validation
- Dredd - API blueprint testing
- Spectral - OpenAPI linting
Source
git clone https://github.com/secondsky/claude-skills/blob/main/plugins/api-contract-testing/skills/api-contract-testing/SKILL.mdView on GitHub Overview
API Contract Testing verifies that APIs honor contracts between consumers and providers without requiring full integration tests. It centers on consumer-driven contracts, schema validation, and tools like Pact to prevent breaking changes and validate OpenAPI specs.
How This Skill Works
Developers author consumer-driven contracts using Pact, describing expected requests and responses. Providers verify against those contracts via provider verification and publish results to a Pact Broker, enabling cross-service compatibility and OpenAPI schema validation.
When to Use It
- Testing microservices communication to ensure contract adherence
- Preventing breaking changes when APIs evolve
- Validating OpenAPI specifications and JSON schemas
- Integrating contract tests into CI/CD pipelines
- Verifying provider implementations against consumer expectations via Pact Broker
Quick Start
- Step 1: Create a Pact consumer test describing expected requests/responses (e.g., GET /users/{id} → 200 with id, name, email)
- Step 2: Run provider verification against the provider base URL and publish results to a Pact Broker
- Step 3: (Optional) Add OpenAPI validation in your Express app to enforce the API schema at runtime
Best Practices
- Test from the consumer perspective using real scenarios
- Use matchers for flexible value validation
- Validate structure, not exact values
- Version contracts explicitly to manage changes
- Run contract tests in CI/CD and verify backward compatibility
Example Use Cases
- A microservice pair (OrderService and UserService) validates contracts with Pact consumer tests
- Provider verification checks a running UserService against consumer contracts and publishes results to a Pact Broker
- OpenAPI validation added to an Express app using express-openapi-validator to enforce API schemas
- CI/CD pipelines run pact:verify and publish outcomes to Pact Broker for traceability
- Cross-language contracts via Pact across Node, Java, and Python services
Frequently Asked Questions
Add this skill to your agents