Skill-Details
api-contract-testing
API contract testing methodology and tooling.
Vor Nutzung prüfen
Die automatische Prüfung bewertet Relevanz, nicht Sicherheit oder Empfehlung. Lies vor der Nutzung die Quellanweisungen.
SKILL.md
Dieser Auszug wurde bei der Prüfung gespeichert. Die externe Quelle enthält die vollständige und aktuelle Version.
---
name: api-contract-testing
description: Verifies API contracts between services using consumer-driven contracts, schema validation, and tools like Pact. Use when testing microservices communication, preventing breaking changes, or validating OpenAPI specifications.
license: MIT
---
# 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)
```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);
});
});
});
```
## Provider Verification
```typescript
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)
```javascript
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](references/python-json-schema.md)
- **Java REST Assured**: See [references/java-rest-assured.md](references/java-rest-assured.md)
- **Pact Broker CI/CD**: See [references/pact-broker-cicd.md](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
Vollständige Quelle auf GitHub lesen (öffnet externe Seite)