Open PortfolioOpen Portfolio.
โ† Back to Blog

The Developer's Guide to API Contract Testing

July 16, 2026at 2:02 PM UTCBy Pocket Portfolio TeamDevelopment
The Developer's Guide to API Contract Testing
#api#testing#developer#guide

Problem

In modern software development, APIs serve as the backbone of communication between services. As systems grow in complexity, ensuring that APIs consistently meet expectations becomes critical. Without proper testing, changes to an API can lead to integration failures, broken functionality, and ultimately, user dissatisfaction. Traditional tests like unit and integration tests often fall short in verifying the exact structure and semantics of API requests and responses. This is where API contract testing steps in, verifying that APIs adhere to a predefined specification, ensuring stability and reliability in service interactions.

Solution with Code

API contract testing involves validating APIs against a contract, typically defined by specifications like OpenAPI or Swagger. By doing so, developers can guarantee that the API functions as expected across different environments and updates. Here, we'll explore a basic implementation using the pact library, a popular choice for contract testing.

First, ensure you have pact installed in your project:

npm install @pact-foundation/pact

Next, create a test file, apiContract.test.js, and set up a basic test:

const { Pact } = require('@pact-foundation/pact');
const path = require('path');
const axios = require('axios');

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

describe('API Contract Testing', () => {
  beforeAll(() => provider.setup());

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

  describe('When a request for user data is made', () => {
    beforeEach(() => {
      const interaction = {
        state: 'user data exists',
        uponReceiving: 'a request for user data',
        withRequest: {
          method: 'GET',
          path: '/user',
          headers: { Accept: 'application/json' },
        },
        willRespondWith: {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
          body: {
            id: 1,
            name: 'John Doe',
          },
        },
      };
      return provider.addInteraction(interaction);
    });

    it('should return the correct user data', async () => {
      const response = await axios.get('http://localhost:1234/user', {
        headers: { Accept: 'application/json' },
      });

      expect(response.status).toBe(200);
      expect(response.data).toEqual({ id: 1, name: 'John Doe' });
    });
  });
});

This setup defines a contract between a consumer and provider, specifying expected requests and responses. It tests if the provider meets this contract, helping catch deviations early in the development process.

Key Concepts

  • Contract Testing: A methodology that ensures that two services (consumer and provider) can communicate with each other by adhering to a shared API contract.

  • Pact: A tool for implementing consumer-driven contract testing, allowing developers to define interactions in a human-readable format.

  • API Specification: A document defining the structure of API requests and responses, such as OpenAPI or Swagger.

API contract testing empowers teams to maintain robust integrations, facilitating smoother deployments and reducing the risks of breaking changes. By implementing contract testing, developers can ensure more reliable and predictable API interactions.

The Developer's Guide to API Contract Testing | Open Portfolio Blog | Open Portfolio