Consumer-Driven Contract Testing with Pact - Code Example

Paul-Sebastian Manole - Aug 5 - - Dev Community

This is a practical code example to accompany the Consumer-Driven Contract Testing with Pact article that I wrote.

Here is how to set up and use Pact with PactFlow for consumer-driven contract testing (CDC) between a React frontend web application (the consumer) and an Express.js REST API (the provider) in the context of a ProductsCatalog API, for the interaction of creating a new product.

Step 1: Set Up Pact in the Consumer (React App)

  • Install Pact in the Consumer Project:
npm install --save-dev @pact-foundation/pact
Enter fullscreen mode Exit fullscreen mode
  • Write a Consumer Pact Test: Create a test file (e.g., pactTests/CreateProductPact.spec.js) in your consumer project:
const { Pact } = require('@pact-foundation/pact');
const path = require('path');
const { createProduct } = require('../src/api'); // Function that makes the API call

const provider = new Pact({
  consumer: 'ProductsCatalogConsumer',
  provider: 'ProductsCatalogAPI',
  port: 1234,
  log: path.resolve(process.cwd(), 'logs', 'pact.log'),
  dir: path.resolve(process.cwd(), 'pacts'),
  logLevel: 'INFO',
  spec: 2,
});

describe('Products API Pact', () => {
  beforeAll(() => provider.setup());

  afterAll(() => provider.finalize());

  beforeEach(() => {
    const interaction = {
      state: 'provider allows product creation',
      uponReceiving: 'a request to create a product',
      withRequest: {
        method: 'POST',
        path: '/products',
        headers: { 'Content-Type': 'application/json' },
        body: {
          name: 'New Product',
          price: 29.99,
        },
      },
      willRespondWith: {
        status: 201,
        headers: { 'Content-Type': 'application/json' },
        body: {
          id: 1,
          name: 'New Product',
          price: 29.99,
        },
      },
    };
    return provider.addInteraction(interaction);
  });

  it('should create a product successfully', async () => {
    const response = await createProduct({ name: 'New Product', price: 29.99 });
    expect(response).toEqual({
      id: 1,
      name: 'New Product',
      price: 29.99,
    });
  });

  afterEach(() => provider.verify());
});
Enter fullscreen mode Exit fullscreen mode
  • Run the Consumer Pact Test:
jest pactTests/CreateProductPact.spec.js
Enter fullscreen mode Exit fullscreen mode

This is typically executed by the CI pipeline together with other unit tests.

  • Publish the Pact File to PactFlow: Create a script (e.g., publishPact.js):
const pact = require('@pact-foundation/pact-node');
const path = require('path');

pact.publishPacts({
  pactFilesOrDirs: [path.resolve(process.cwd(), 'pacts')],
  pactBroker: '[https://your-pactflow-url](https://your-pactflow-url)',
  consumerVersion: '1.0.0',
  tags: ['prod'],
});
Enter fullscreen mode Exit fullscreen mode
  • Run the script:
node publishPact.js
Enter fullscreen mode Exit fullscreen mode

This is typically executed by the CI pipeline after all tests pass with green lights.

Step 2: Set Up Pact in the Provider (Express.js API)

  • Install Pact in the Provider Project:
npm install --save-dev @pact-foundation/pact
Enter fullscreen mode Exit fullscreen mode
  • Write a Provider Verification Test: Create a test file (e.g., pactTests/VerifyPacts.spec.js) in your provider project:
const { Verifier } = require('@pact-foundation/pact');
const path = require('path');
const server = require('../src/server'); // Your Express app

server.listen(8080, () => {
  console.log('Provider API listening on [http://localhost:8080'](http://localhost:8080'));
});

describe('Pact Verification', () => {
  it('validates the expectations of ProductsCatalogConsumer', () => {
    return new Verifier({
      provider: 'ProductsCatalogAPI',
      providerBaseUrl: '[http://localhost:8080](http://localhost:8080)',
      pactBrokerUrl: '[https://your-pactflow-url](https://your-pactflow-url)',
      providerVersion: '1.0.0',
      tags: ['prod'],
      publishVerificationResult: true,
    }).verifyProvider();
  });
});
Enter fullscreen mode Exit fullscreen mode
  • Run the Provider Verification Test:
jest pactTests/VerifyPacts.spec.js
Enter fullscreen mode Exit fullscreen mode

This is typically executed by the CI pipeline together with other unit tests.

Step 3: Configure PactFlow

  1. Set Up PactFlow:
    • Sign up for a PactFlow account and create a new workspace.
    • Obtain the PactFlow URL and authentication token.
  2. Configure CI/CD Pipelines:
    • Ensure your CI/CD pipeline runs the consumer tests, publishes the pacts to PactFlow, and then triggers the provider verification tests.

Summary of the workflow

  1. Consumer (React App):
    • Write consumer tests using Pact.
    • Generate Pact files during test execution.
    • Publish Pact files to PactFlow.
  2. Provider (Express.js API):
    • Fetch Pact files from PactFlow.
    • Verify the provider against the Pact files.
    • Publish verification results back to PactFlow.

By following these steps, you ensure that both the consumer and provider are aligned through the contract, facilitating seamless integration and continuous delivery.

. .
Terabox Video Player