Skip to main content
Marco Rossi·

Pact consumer test that breaks the provider build the moment they rename a response field

Implement consumer-driven contract tests between microservices using Pact or similar tools to prevent breaking API changes.

Contract Testing with Pact / Consumer-Driven

You are a microservices testing architect specializing in contract testing. Implement consumer-driven contract tests for the following service interactions. **Consumer Service:** {{consumer_service}} **Provider Service:** {{provider_service}} **API Interactions:** {{api_interactions}} **Tech Stack:** {{tech_stack}} **Contract Testing Tool:** {{contract_tool}} **CI/CD Platform:** {{cicd_platform}} Generate: 1. **Consumer Contract Tests**: Pact consumer tests defining expected interactions: - Request matchers (flexible matching rules) - Response body matchers with type and regex constraints - Provider state setup for each interaction - Error response contracts (4xx, 5xx) 2. **Provider Verification Tests**: Pact provider verification setup: - State management handlers - Provider-side test data setup - Verification against published contracts 3. **Pact Broker Configuration**: Contract publishing and verification workflow 4. **CI Integration Pipeline**: - Consumer: publish contracts on build - Provider: verify contracts before deployment - Can-I-Deploy gate checking 5. **Bi-Directional Contracts**: OpenAPI spec as provider contract if applicable 6. **Breaking Change Detection**: Automated detection of contract modifications 7. **Version Strategy**: Contract versioning aligned with service versioning 8. **Webhook Setup**: Automatic provider verification trigger on contract change 9. **Failure Diagnostics**: How to debug contract test failures 10. **Team Workflow**: Development workflow preventing breaking changes Output complete test implementations and CI configuration.

Ergebnisse

Consumer-driven contract test between a `web-bff` consumer and an `orders-api` provider using Pact (JS). Prevents the provider from shipping a breaking response shape. ```typescript // consumer: web-bff/test/orders.pact.test.ts import { PactV3, MatchersV3 } from "@pact-foundation/pact"; const { like, eachLike, regex } = MatchersV3; const provider = new PactV3({ consumer: "web-bff", provider: "orders-api" }); describe("orders-api contract", () => { it("returns an order by id", async () => { provider .given("an order 42 exists") // provider state .uponReceiving("a request for order 42") .withRequest({ method: "GET", path: "/orders/42" }) .willRespondWith({ status: 200, body: { id: like("42"), status: regex("pending|shipped|cancelled", "pending"), totalCents: like(4198), items: eachLike({ sku: like("SKU-004521"), qty: like(1) }), }, }); await provider.executeTest(async (mock) => { const res = await fetch(`${mock.url}/orders/42`); expect(res.status).toBe(200); }); }); }); ``` The matchers (`like`, `regex`, `eachLike`) assert on *type and shape*, not exact values — so the contract stays robust to data changes but breaks the moment the provider drops a field or changes a type. **Provider side** replays the published pact against `orders-api`, using a state handler that seeds "an order 42 exists" before the verification request. **CI flow:** consumer publishes the contract to the Pact Broker on build; the provider's pipeline runs verification and a `can-i-deploy` gate blocks its release if the contract isn't satisfied. **Result:** a provider engineer who renames `totalCents → total` gets a red build before it ever reaches the consumer.

Modell: Claude Sonnet 4

8 Likes2 SavesScore: 5