Contract Test Validator
Overview
Validate API contracts between services using consumer-driven contract testing to prevent breaking changes in microservice architectures. Supports Pact (the industry standard for CDC testing), Spring Cloud Contract (JVM), and OpenAPI-diff for specification comparison.
Prerequisites
- Contract testing framework installed (Pact JS/Python/JVM, or Spring Cloud Contract)
- Pact Broker running (or PactFlow SaaS) for contract storage and verification
- Consumer and provider services with clearly defined API boundaries
- Existing integration points documented (which consumers call which provider endpoints)
- CI pipeline configured for both consumer and provider repositories
Instructions
- Identify consumer-provider relationships in the system:
- Map which services call which APIs (e.g., Frontend calls User API, Order API calls Payment API).
- Document each interaction: HTTP method, path, headers, request body, expected response.
- Prioritize contracts for the most critical and frequently changing integrations.
- Write consumer-side contract tests (Pact consumer tests):
- Define the expected interaction: method, path, query parameters, headers, request body.
- Specify the expected response: status code, headers, and response body structure.
- Use matchers for flexible assertions (
like(), eachLike(), term()) instead of exact values.
- Generate a Pact file (JSON contract) from the consumer test.
- Publish consumer contracts to the Pact Broker:
- Run
pact-broker publish with the consumer version and branch/tag.
- Enable webhooks to trigger provider verification when new contracts are published.
- Configure can-i-deploy checks in CI to gate deployments.
- Write provider-side verification tests:
- Configure the Pact verifier to fetch contracts from the Pact Broker.
- Set up provider states (test data scenarios matching consumer expectations).
- Run verification against the actual provider implementation.
- Publish verification results back to the Pact Broker.
- Handle contract evolution:
- Adding new fields: Safe -- consumers using matchers will not break.
- Removing fields: Breaking -- coordinate with all consumers before removal.
- Changing field types: Breaking -- requires consumer updates first.
- Use
can-i-deploy to check compatibility before releasing either side.
- For schema-based validation (non-Pact):
- Compare OpenAPI spec versions using
openapi-diff to detect breaking changes.
- Flag removed endpoints, changed parameter types, and narrowed response schemas.
- Run schema validation tests against the actual API responses.
- Integrate contract tests into the CI/CD pipeline for both consumers and providers.
Output
- Consumer Pact test files defining expected API interactions
- Generated Pact contract files (JSON) in
pacts/ directory
- Provider verification test configuration
- Pact Broker deployment with published contracts and verification status
- CI pipeline integration with
can-i-deploy deployment gates
- Contract evolution report flagging breaking vs. non-breaking changes
Error Handling
| Error |
Cause |
Solution |
| Provider verification fails |
Provider response does not match consumer expectations |
Check if the contract is outdated; update consumer tests if the change is intentional; fix provider if regression |
can-i-deploy blocks release |
Consumer has unverified or failed contracts |
Run provider verification; check if the right version tags are published; verify Pact Broker webhook fired |
| Pact Broker connection error |
Broker URL or credentials misconfigured |
Verify PACT_BROKER_BASE_URL and PACT_BROKER_TOKEN environment variables; check network connectivity |
| Provider state not found |
Consumer test references a state the provider does not implement |
Add the missing provider state setup function; align state names between consumer and provider |
| Too many contracts to maintain |
Every consumer-provider pair has extensive contracts |
Focus on critical interactions; use matchers instead of exact values; consolidate similar interactions |
Examples
Pact consumer test (JavaScript):
import { PactV4 } from '@pact-foundation/pact';
const provider = new PactV4({ consumer: 'Frontend', provider: 'UserAPI' });
describe('User API Contract', () => {
it('fetches a user by ID', async () => {
await provider
.addInteraction()
.given('user with ID 1 exists')
.uponReceiving('a request for user 1')
.withRequest('GET', '/api/users/1', (builder) => {
builder.headers({ Accept: 'application/json' });
})
.willRespondWith(200, (builder) => { # HTTP 200 OK
builder
.headers({ 'Content-Type': 'application/json' })
.jsonBody({
id: like('1'),
name: like('Alice'),
email: like('alice@example.com'),
});
})
.executeTest(async (mockServer) => {
const response = await fetch(`${mockServer.url}/api/users/1`);
const user = await response.json();
expect(user.name).toBeDefined();
});
});
});
Provider verification test:
import { Verifier } from '@pact-foundation/pact';
describe('User API Provider Verification', () => {
it('validates consumer contracts', async () => {
await new Verifier({
providerBaseUrl: 'http://localhost:3000', # 3000: 3 seconds in ms
pactBrokerUrl: process.env.PACT_BROKER_BASE_URL,
pactBrokerToken: process.env.PACT_BROKER_TOKEN,
provider: 'UserAPI',
publishVerificationResult: true,
providerVersion: process.env.GIT_SHA,
stateHandlers: {
'user with ID 1 exists': async () => {
await db.users.create({ id: '1', name: 'Alice', email: 'alice@example.com' });
},
},
}).verifyProvider();
});
});
can-i-deploy CI check:
pact-broker can-i-deploy \
--pacticipant Frontend \
--version $(git rev-parse HEAD) \
--to-environment production \
--broker-base-url $PACT_BROKER_URL \
--broker-token $PACT_BROKER_TOKEN
Resources
1---2name: validating-api-contracts3description: Validate API contracts using consumer-driven contract testing (Pact, Spring Cloud Contract). Use when performing specialized testing. Trigger with phrases like "validate API contract", "run contract tests", or "check consumer contracts".4license: MIT5---6# Contract Test Validator
7
8## Overview
9
10Validate API contracts between services using consumer-driven contract testing to prevent breaking changes in microservice architectures. Supports Pact (the industry standard for CDC testing), Spring Cloud Contract (JVM), and OpenAPI-diff for specification comparison.
11
12## Prerequisites
13
14- Contract testing framework installed (Pact JS/Python/JVM, or Spring Cloud Contract)
15- Pact Broker running (or PactFlow SaaS) for contract storage and verification
16- Consumer and provider services with clearly defined API boundaries
17- Existing integration points documented (which consumers call which provider endpoints)
18- CI pipeline configured for both consumer and provider repositories
19
20## Instructions
21
221. Identify consumer-provider relationships in the system:
23 - Map which services call which APIs (e.g., Frontend calls User API, Order API calls Payment API).
24 - Document each interaction: HTTP method, path, headers, request body, expected response.
25 - Prioritize contracts for the most critical and frequently changing integrations.
262. Write consumer-side contract tests (Pact consumer tests):
27 - Define the expected interaction: method, path, query parameters, headers, request body.
28 - Specify the expected response: status code, headers, and response body structure.
29 - Use matchers for flexible assertions (`like()`, `eachLike()`, `term()`) instead of exact values.
30 - Generate a Pact file (JSON contract) from the consumer test.
313. Publish consumer contracts to the Pact Broker:
32 - Run `pact-broker publish` with the consumer version and branch/tag.
33 - Enable webhooks to trigger provider verification when new contracts are published.
34 - Configure can-i-deploy checks in CI to gate deployments.
354. Write provider-side verification tests:
36 - Configure the Pact verifier to fetch contracts from the Pact Broker.
37 - Set up provider states (test data scenarios matching consumer expectations).
38 - Run verification against the actual provider implementation.
39 - Publish verification results back to the Pact Broker.
405. Handle contract evolution:
41 - Adding new fields: Safe -- consumers using matchers will not break.
42 - Removing fields: Breaking -- coordinate with all consumers before removal.
43 - Changing field types: Breaking -- requires consumer updates first.
44 - Use `can-i-deploy` to check compatibility before releasing either side.
456. For schema-based validation (non-Pact):
46 - Compare OpenAPI spec versions using `openapi-diff` to detect breaking changes.
47 - Flag removed endpoints, changed parameter types, and narrowed response schemas.
48 - Run schema validation tests against the actual API responses.
497. Integrate contract tests into the CI/CD pipeline for both consumers and providers.
50
51## Output
52
53- Consumer Pact test files defining expected API interactions
54- Generated Pact contract files (JSON) in `pacts/` directory
55- Provider verification test configuration
56- Pact Broker deployment with published contracts and verification status
57- CI pipeline integration with `can-i-deploy` deployment gates
58- Contract evolution report flagging breaking vs. non-breaking changes
59
60## Error Handling
61
62| Error | Cause | Solution |
63|-------|-------|---------|
64| Provider verification fails | Provider response does not match consumer expectations | Check if the contract is outdated; update consumer tests if the change is intentional; fix provider if regression |
65| `can-i-deploy` blocks release | Consumer has unverified or failed contracts | Run provider verification; check if the right version tags are published; verify Pact Broker webhook fired |
66| Pact Broker connection error | Broker URL or credentials misconfigured | Verify `PACT_BROKER_BASE_URL` and `PACT_BROKER_TOKEN` environment variables; check network connectivity |
67| Provider state not found | Consumer test references a state the provider does not implement | Add the missing provider state setup function; align state names between consumer and provider |
68| Too many contracts to maintain | Every consumer-provider pair has extensive contracts | Focus on critical interactions; use matchers instead of exact values; consolidate similar interactions |
69
70## Examples
71
72**Pact consumer test (JavaScript):**
73
74```typescript
75import { PactV4 } from '@pact-foundation/pact';
76
77const provider = new PactV4({ consumer: 'Frontend', provider: 'UserAPI' });
78
79describe('User API Contract', () => {
80 it('fetches a user by ID', async () => {
81 await provider
82 .addInteraction()
83 .given('user with ID 1 exists')
84 .uponReceiving('a request for user 1')
85 .withRequest('GET', '/api/users/1', (builder) => {
86 builder.headers({ Accept: 'application/json' });
87 })
88 .willRespondWith(200, (builder) => { # HTTP 200 OK
89 builder
90 .headers({ 'Content-Type': 'application/json' })
91 .jsonBody({
92 id: like('1'),
93 name: like('Alice'),
94 email: like('alice@example.com'),
95 });
96 })
97 .executeTest(async (mockServer) => {
98 const response = await fetch(`${mockServer.url}/api/users/1`);
99 const user = await response.json();
100 expect(user.name).toBeDefined();
101 });
102 });
103});
104```
105
106**Provider verification test:**
107
108```typescript
109import { Verifier } from '@pact-foundation/pact';
110
111describe('User API Provider Verification', () => {
112 it('validates consumer contracts', async () => {
113 await new Verifier({
114 providerBaseUrl: 'http://localhost:3000', # 3000: 3 seconds in ms
115 pactBrokerUrl: process.env.PACT_BROKER_BASE_URL,
116 pactBrokerToken: process.env.PACT_BROKER_TOKEN,
117 provider: 'UserAPI',
118 publishVerificationResult: true,
119 providerVersion: process.env.GIT_SHA,
120 stateHandlers: {
121 'user with ID 1 exists': async () => {
122 await db.users.create({ id: '1', name: 'Alice', email: 'alice@example.com' });
123 },
124 },
125 }).verifyProvider();
126 });
127});
128```
129
130**can-i-deploy CI check:**
131
132```bash
133pact-broker can-i-deploy \
134 --pacticipant Frontend \
135 --version $(git rev-parse HEAD) \
136 --to-environment production \
137 --broker-base-url $PACT_BROKER_URL \
138 --broker-token $PACT_BROKER_TOKEN
139```
140
141## Resources
142
143- Pact documentation: https://docs.pact.io/
144- PactFlow (managed Pact Broker): https://pactflow.io/
145- Spring Cloud Contract: https://spring.io/projects/spring-cloud-contract
146- openapi-diff: https://github.com/OpenAPITools/openapi-diff
147- Consumer-Driven Contracts: https://martinfowler.com/articles/consumerDrivenContracts.html