DEV Community

Paul-Sebastian Manole
Paul-Sebastian Manole

Posted on • Updated on

Consumer-Driven Contract Testing with Pact - Code Example

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.

Top comments (0)