← Back to all projects

LEARN PACT CONTRACT TESTING

In the era of microservices, distributed systems are the norm. Services developed by independent teams need to communicate reliably. Traditional end-to-end integration tests are slow, brittle, and often fail to pinpoint the exact cause of an integration failure. They also provide feedback too late in the development cycle. This is where Consumer-Driven Contract Testing, pioneered and popularized by tools like Pact, steps in.

Learn Consumer-Driven Contract Testing with Pact: From Zero to Best Practices Master

Goal: Deeply understand Consumer-Driven Contract (CDC) Testing using the Pact framework—what it is, why it’s essential for modern distributed systems, how to implement it effectively, and master the best practices that ensure robust, decoupled, and rapidly evolving microservices. You’ll learn to prevent integration issues before they hit production, foster collaboration between teams, and build confidence in your service integrations.


Why Consumer-Driven Contract Testing with Pact Matters

In the era of microservices, distributed systems are the norm. Services developed by independent teams need to communicate reliably. Traditional end-to-end integration tests are slow, brittle, and often fail to pinpoint the exact cause of an integration failure. They also provide feedback too late in the development cycle. This is where Consumer-Driven Contract Testing, pioneered and popularized by tools like Pact, steps in.

Pact emerged from the need to manage the complexity of integrating numerous services, especially in agile environments where services evolve rapidly. It shifts the focus from “does the whole system work?” to “does my service correctly fulfill its contracts with its consumers?”. This approach empowers teams to develop and deploy services independently, with high confidence that their integrations will work in production.

The Problem CDC Testing Solves

Imagine two services: a ProductService (provider) and an OrderService (consumer). The OrderService calls the ProductService to get product details.

Without CDC testing:

  • OrderService team writes integration tests against a deployed ProductService. These tests are slow and require the ProductService to be available.
  • ProductService team changes an API response field.
  • OrderService integration tests fail, but only after deployment or a long test run.
  • Debugging is hard: Is it OrderService’s fault or ProductService’s?
  • Teams are blocked waiting for each other.

With CDC testing:

  • OrderService team defines a “contract” of what it expects from ProductService.
  • This contract is automatically verified against ProductService’s codebase during its build.
  • If ProductService breaks the contract, its build fails immediately.
  • OrderService can develop and test against a mock of ProductService generated from the contract, without needing the real service.

Core Concept Analysis

1. The CDC Workflow

[Consumer Team]                  [Contract Repository]                [Provider Team]
      |                                   |                                  |
1. Write Unit Test                        |                                  |
2. Pact Mock Gen Pact File ----------> 3. Publish Pact                       |
      |                                   |                                  |
      |                                   | <---------- 4. Fetch Pact for Verification
      |                                   |                                  |
      |                                   |                         5. Verify against REAL code
      |                                   |                                  |
      | <---------------------------------V------------------------- 6. Publish Results

2. The Contract (Pact File)

A Pact file is a JSON document that records the interactions (requests and expected responses) between a consumer and a provider. It’s the single source of truth.

3. Provider States

This is the “Given” part of the contract. It tells the provider: “Assume the system is in this state before I make this request” (e.g., “Given a user with ID 5 exists”).


Concept Summary Table

Concept Cluster What You Need to Internalize
Consumer-Driven The consumer defines the requirements, ensuring the provider only builds what is actually needed.
Pact Mock Service A mock server that acts like the provider during consumer tests, ensuring the consumer code works as expected.
Pact Verifier A tool that replays consumer requests from the Pact file against the real provider service.
Pact Broker A central server that stores, versions, and provides visibility into contracts and verification results.
Matching Rules Using regex or type-based matching instead of static values to make contracts flexible and robust.

Deep Dive Reading by Concept

Concept Book & Chapter
Testing Strategies Building Microservices by Sam Newman — Ch. 10: “Testing”
Integration Points Release It! by Michael Nygard — Ch. 1: “Stability Patterns”
API Design Design and Build Great Web APIs by Mike Amundsen — Ch. 3: “Designing APIs”

Project 1: Your First Consumer Pact

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js (JavaScript/TypeScript)
  • Alternative Programming Languages: Python, Java, Go
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: API Mocking
  • Software or Tool: Pact JS
  • Main Book: “Building Microservices” by Sam Newman

What you’ll build: A small client library for an OrderService that fetches product details. You’ll write a test that uses Pact to mock the ProductService and generate a JSON contract file.

Why it teaches Pact: You learn the DSL (Domain Specific Language) of Pact. You’ll see how uponReceiving, withRequest, and willRespondWith create a formal specification of your code’s expectations.

Core challenges you’ll face:

  • Configuring the Pact Mock Server.
  • Aligning headers (e.g., Content-Type: application/json).
  • Handling asynchronous test execution.

Real World Outcome

You will see a pacts/ folder generated in your project containing a JSON file that describes the exact HTTP interaction your code expects.

Example Output:

{
  "consumer": { "name": "OrderService" },
  "provider": { "name": "ProductService" },
  "interactions": [
    {
      "description": "a request for product 123",
      "request": {
        "method": "GET",
        "path": "/products/123"
      },
      "response": {
        "status": 200,
        "body": { "id": "123", "name": "Widget" }
      }
    }
  ]
}

The Core Question You’re Answering

“How can I document my service’s dependencies in a way that is automatically verifiable by the team providing those dependencies?”


Project 2: The Provider Verification

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js (Express)
  • Alternative Programming Languages: Flask, Spring Boot
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: API Testing
  • Software or Tool: Pact Provider Verifier
  • Main Book: “Building Microservices” by Sam Newman

What you’ll build: A simple ProductService API using Express. You will run a script that takes the Pact file from Project 1 and verifies it against this running API.

Why it teaches Pact: This is the “Aha!” moment. You see the Pact Verifier act as a “smart client” that replays the consumer’s request and checks if your actual code produces the expected result.

Core challenges you’ll face:

  • Running the provider in a testable state.
  • Dealing with port conflicts.
  • Mapping contract descriptions to code execution.

Real World Outcome

A terminal output showing the verification steps passing or failing.

Example Output:

Verifying a pact between OrderService and ProductService
  a request for product 123
    returns a response which
      has status 200 (OK)
      has a matching body (OK)

The Core Question You’re Answering

“How can I be sure that the change I just made to my API won’t break the client services that rely on it?”


Project 3: Centralizing with the Pact Broker

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Docker / Shell
  • Alternative Programming Languages: Terraform, Kubernetes
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DevOps / Infrastructure
  • Software or Tool: Pact Broker (Docker)
  • Main Book: “Continuous Delivery” by Jez Humble

What you’ll build: You will spin up a Pact Broker using Docker Compose. You will then modify your scripts from Project 1 and 2 to publish and fetch contracts from this broker instead of using local files.

Why it teaches Pact: In a real company, you don’t pass JSON files around. The Broker is the “glue” that allows teams to collaborate. You’ll understand the lifecycle of a contract from publication to verification.

Core challenges you’ll face:

  • Setting up a database (Postgres) for the Broker.
  • Authenticating with the Broker (API Keys/Tokens).
  • Understanding the “Consumer Version” and “Provider Version” concepts.

Real World Outcome

You’ll have a web UI where you can see the “network graph” of your services and the status of their integrations.

Example Output:

$ pact-broker publish ./pacts --broker-base-url http://localhost:9292 --consumer-app-version 1.0.0
Successfully published pacts to http://localhost:9292

The Core Question You’re Answering

“How do we manage hundreds of contracts across dozens of teams without losing track of who is compatible with whom?”

—## Project 4: Flexible Matching (Robust Matchers)

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js
  • Alternative Programming Languages: Any
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Protocol Design
  • Software or Tool: Pact Matchers (V3/V4)
  • Main Book: “Design and Build Great Web APIs” by Mike Amundsen

What you’ll build: You will update your OrderService contract to use Matchers instead of exact values. Instead of expecting id: "123", you’ll expect id: like("abc") or price: decimal(10.5).

Why it teaches Pact: Contracts fail in production if they are too rigid. Matchers allow you to say “I expect a string here” or “I expect this regex pattern,” which makes your contract robust to data changes that don’t break the structure.


Real World Outcome

A Pact file that contains “matching rules” alongside the sample values.

Example Output (Pact File):

"body": {
  "id": "abc",
  "price": 10.5
},
"matchingRules": {
  "$.body.id": { "match": "type" },
  "$.body.price": { "match": "decimal" }
}

The Core Question You’re Answering

“How can I define a contract that is specific enough to catch errors but flexible enough to not break when the provider changes unimportant details?”


Project 5: Provider States (Setup/Teardown)

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js / Express
  • Alternative Programming Languages: Any
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Backend Engineering
  • Software or Tool: Pact Provider State Handlers
  • Main Book: “Working Effectively with Legacy Code” by Michael Feathers

What you’ll build: A scenario where the consumer requests a product that must exist in the database. You’ll implement a “State Handler” on the provider side that inserts that specific product into a test database before the Pact test runs.

Why it teaches Pact: It forces you to think about how to put your application into a specific state programmatically. It’s the bridge between a “dumb” replay and a “smart” integration test.


Real World Outcome

The provider verification logs will show the “State Handler” being called before the request is replayed.

Example Output:

Verifying a pact between OrderService and ProductService
  Given a product with ID 123 exists
    - Setting up state: a product with ID 123 exists... DONE
    with GET /products/123
      returns a response which
        has status 200 (OK)

Project 6: Mutating State (POST/PUT Contracts)

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js
  • Alternative Programming Languages: Any
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: API Design
  • Software or Tool: Pact JS
  • Main Book: “Design and Build Great Web APIs” by Mike Amundsen

What you’ll build: A contract for creating a new order. The consumer sends a JSON body, and the provider is expected to return a 201 Created with the new ID.

Why it teaches Pact: Testing POST requires validating the request body. You’ll learn how the provider verification checks that the consumer is sending valid data.


Project 7: The “Can I Deploy?” Safety Valve

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Bash / CI Config (GitHub Actions)
  • Alternative Programming Languages: GitLab CI, Jenkins
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: CI/CD / DevOps
  • Software or Tool: Pact CLI (can-i-deploy)
  • Main Book: “Continuous Delivery” by Jez Humble

What you’ll build: A CI/CD pipeline where the OrderService build cannot finish until it checks with the Pact Broker if its version is compatible with the currently deployed version of the ProductService.

Why it teaches Pact: This is the ultimate goal of Pact. It replaces manual “staging” environments with a mathematical proof of compatibility. You’ll learn how to use the can-i-deploy tool to protect your production environment.


Real World Outcome

A CI/CD job that fails if you attempt to deploy a breaking change.

Example Output (GitHub Actions):

$ pact-broker can-i-deploy --pacticipant OrderService --version 1.0.5 --to production
Computer says no! 
The following integrations are not compatible:
- OrderService (v1.0.5) and ProductService (v2.0.0)
Reason: Contract for GET /products/123 has not been verified by ProductService v2.0.0
Error: Process exited with code 1

The Core Question You’re Answering

“How can we stop deploying to a staging environment just to see if things break, and instead know they will work before we even merge the code?”


Project 8: Asynchronous Messaging (Async Pact)

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js
  • Alternative Programming Languages: Java, Go
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 4: Expert
  • Knowledge Area: Distributed Systems / Event-Driven Architecture
  • Software or Tool: Pact Message
  • Main Book: “Designing Data-Intensive Applications” by Martin Kleppmann

What you’ll build: A contract for a message published to a Kafka or SQS queue. Instead of HTTP, you’ll define a contract for a JSON payload that the EmailService expects to consume when an OrderCreated event occurs.

Why it teaches Pact: Most modern systems are event-driven. You’ll learn how to verify that the producer of a message sends what the consumer expects, without needing a running broker like Kafka during the test.


Project 9: Bi-Directional Contract Testing

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js + OpenAPI (Swagger)
  • Alternative Programming Languages: Any
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: API Standards
  • Software or Tool: Pactflow Bi-Directional
  • Main Book: “Design and Build Great Web APIs” by Mike Amundsen

What you’ll build: An integration where you don’t use the Pact DSL on the provider side. Instead, you’ll use an existing OpenAPI (Swagger) specification and verify the consumer’s Pact against that specification.


Project 10: Breaking Changes & Migration

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Any
  • Alternative Programming Languages: Any
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Software Evolution
  • Software or Tool: Pact Broker
  • Main Book: “Refactoring” by Martin Fowler

What you’ll build: A controlled “Breaking Change.” You will intentionally rename a field on the Provider and watch the “Can I Deploy” check fail. Then, you will implement a “Parallel Change” (Add new field, keep old field) and see it pass.


Project 11: Frontend Development with Pacts

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: React / Vue / Angular
  • Alternative Programming Languages: Any Frontend framework
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Frontend Engineering
  • Software or Tool: Pact Stub Server
  • Main Book: “Building Microservices” by Sam Newman

What you’ll build: A React dashboard that displays product data. Instead of calling a real API or hardcoding JSON mocks, you’ll use the Pact file from Project 1 to spin up a Pact Stub Server.

Why it teaches Pact: It shows how Pacts can be used as “Living Documentation” and “Mock Servers” for frontend teams. This ensures that the UI is developed against the exact specification the backend team is working on.


Project 12: Custom Matchers & V3 Features

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: TypeScript
  • Alternative Programming Languages: Java
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Data Validation
  • Software or Tool: Pact V3 Specification
  • Main Book: “Code Complete” by Steve McConnell

What you’ll build: A contract that uses advanced V3 features like eachLike, atLeastOneLike, and dateTime matchers. You’ll create a complex response with nested arrays of objects.


Project 13: Polyglot Pact (Crossing Languages)

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Python (Consumer) / Go (Provider)
  • Alternative Programming Languages: Any language pair
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Cross-Language Integration
  • Software or Tool: Pact CLI / Pact Broker
  • Main Book: “Building Microservices” by Sam Newman

What you’ll build: A Python script that acts as a consumer and a Go service that acts as a provider. You will share the contract through the Pact Broker.


Project 14: Security & Auth Contract Testing

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js
  • Alternative Programming Languages: Any
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Security / Authentication
  • Software or Tool: JWT / OAuth2
  • Main Book: “API Security in Action” by Neil Madden

What you’ll build: A contract that includes an Authorization header with a Bearer token. You’ll verify that the provider correctly rejects requests with missing or malformed tokens (401/403 status).


Project 15: GraphQL Contract Testing

  • File: LEARN_PACT_CONTRACT_TESTING.md
  • Main Programming Language: Node.js (Apollo/GraphQL)
  • Alternative Programming Languages: Any GraphQL stack
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 5. The “Industry Disruptor”
  • Difficulty: Level 4: Expert
  • Knowledge Area: GraphQL / Modern APIs
  • Software or Tool: Pact GraphQL DSL
  • Main Book: “Learning GraphQL” by Eve Porcello and Alex Banks

What you’ll build: A Pact test for a GraphQL query. You’ll define the query, variables, and the expected data structure in the response.


Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
1. Consumer Pact Beginner Weekend ★☆☆☆☆ ★★☆☆☆
2. Provider Verification Beginner Weekend ★★☆☆☆ ★★☆☆☆
3. Pact Broker Intermediate 1-2 days ★★★☆☆ ★★★☆☆
4. Matchers Intermediate 1 day ★★★☆☆ ★★☆☆☆
5. Provider States Advanced 2-3 days ★★★★☆ ★★★☆☆
7. Can I Deploy? Advanced 1 week ★★★★☆ ★★★★☆
8. Async Messaging Expert 1-2 weeks ★★★★★ ★★★★☆
13. Polyglot Pact Advanced 1 week ★★★★☆ ★★★★☆
15. GraphQL Expert 2 weeks ★★★★★ ★★★★★

Recommendation

If you are a Backend Developer, start with Project 1 and 2 to understand the basic loop. If you are a DevOps Engineer, focus on Project 3 and 7 to master the infrastructure and deployment safety.


Final Overall Project: The “Safe-Deploy” E-Commerce Suite

What you’ll build: A complete e-commerce ecosystem consisting of:

  1. Frontend (React): Uses Pacts to stub its backend dependency.
  2. Order Service (Node.js): A consumer of Product and User services.
  3. Product Service (Go): A provider that manages an inventory.
  4. Notification Service (Python): An async consumer of “Order Placed” events.
  5. CI/CD Pipeline: Fully automated with a Pact Broker, ensuring that no service can be deployed unless its contracts are verified.

Why it teaches Pact: This project simulates a real-world company. You’ll deal with multiple languages, multiple communication styles (HTTP and Async), and the orchestration required to keep everything compatible. You will witness first-hand how Pact allows you to deploy the Product Service without ever worrying if you’ve broken the Order Service.


Summary

This learning path covers Consumer-Driven Contract Testing through 15 hands-on projects. Here’s the complete list:

# Project Name Main Language Difficulty Time Estimate
1 Your First Consumer Pact Node.js Beginner Weekend
2 The Provider Verification Node.js Beginner Weekend
3 Centralizing with the Broker Docker Intermediate 1-2 days
4 Flexible Matching Node.js Intermediate 1 day
5 Provider States Node.js Advanced 2-3 days
6 POST/PUT Contracts Node.js Intermediate 1 day
7 “Can I Deploy?” Bash/YAML Advanced 1 week
8 Asynchronous Messaging Node.js Expert 1-2 weeks
9 Bi-Directional Testing Node.js Advanced 1 week
10 Breaking Changes Any Advanced 3-4 days
11 Frontend Stubbing React Intermediate 2 days
12 Custom Matchers TS Advanced 2 days
13 Polyglot Pact Python/Go Advanced 1 week
14 Security/Auth Node.js Advanced 3 days
15 GraphQL Pact Node.js Expert 2 weeks

For beginners: Start with projects #1, #2, #4. For intermediate: Jump to projects #3, #5, #6, #11. For advanced: Focus on projects #7, #8, #13, #15.

Expected Outcomes

After completing these projects, you will:

  • Understand the paradigm shift from “Integration Testing” to “Contract Testing.”
  • Be proficient in writing consumer-side mocks that generate valid contracts.
  • Know how to implement provider-side verification with complex state management.
  • Master the Pact Broker for CI/CD integration and deployment safety.
  • Be able to apply contract testing to REST, Messaging, and GraphQL architectures.

You’ll have built 15 working projects that demonstrate deep understanding of Consumer-Driven Contract Testing from first principles.