Skip to content
2 min read

Consumer-Driven Contract Testing with Pact

How contract testing catches integration breakages between microservices long before they reach a slow, brittle end-to-end suite.

  • Pact
  • Contract Testing
  • API
  • Microservices

In a microservices world, the riskiest bugs live between services. End-to-end tests catch them late and slowly. Contract testing with Pact catches them early and fast.

The core idea

The consumer defines what it expects from the provider — the shape of a request and the response it needs. Pact records this as a contract, then verifies the provider actually honours it.

  • The consumer test generates a pact file (the contract).
  • The provider replays that contract against its real implementation.
  • If the provider changes in a breaking way, provider verification fails — before anything is deployed.

A consumer expectation

await provider.addInteraction({
  state: "a user with id 1 exists",
  uponReceiving: "a request for user 1",
  withRequest: { method: "GET", path: "/users/1" },
  willRespondWith: {
    status: 200,
    body: { id: 1, email: like("ada@example.com") },
  },
});

Why it beats end-to-end for integrations

  • Fast: no full environment, no browser — just HTTP expectations.
  • Precise: failures point directly at the contract that broke.
  • Decoupled: teams can develop and deploy independently, confident they haven't broken consumers.

A Pact Broker ties it together, storing contracts and verification results so both sides always know whether they're compatible. Use contract tests for the seams between services, and reserve end-to-end tests for a handful of critical user journeys.