DEV Community

Paul-Sebastian Manole
Paul-Sebastian Manole

Posted on • Edited on

Consumer-Driven Contract Testing with Pact - Code Example

NOTE: This is a very short and super high-level example of how one might implement consumer-driven contract testing with Pact. It's meant to convey the principles and make it seem less daunting to start implementing. This continues from where I left off in my first article.

Consumer-Driven Contract Testing with Pact: A Recap

Consumer-Driven Contract Testing (CDCT) is a testing approach that ensures compatibility between services by having the consumer define the expectations for how it interacts with the provider. Pact is a popular tool for implementing CDCT, allowing you to verify that both consumer and provider are aligned in their interactions.

In CDCT, the consumer application defines contracts that specify the requests it expects the provider to fulfill. These contracts are then shared with the provider, which runs verification tests to confirm it can meet the consumer's expectations. This process fosters clear and efficient communication between teams, ensuring that changes in one service don’t break another.

Why Pact?

See the first article in the series.

Key Concepts in Pact

  • Consumer: The application that sends requests and expects responses.
  • Provider: The service that fulfills requests made by the consumer.
  • Pact Contract: The agreement, defined by the consumer, specifying expected request-response pairs.
  • Verification: The provider validates the contract, ensuring it meets consumer expectations.
  • Pact Broker: An optional service that stores and shares contracts, making collaboration easier.

Getting Started: Code Example

Let's implement CDCT with a simple Node.js example using Pact. First, set up your project and install Pact dependencies:

npm init -y
npm install @pact-foundation/pact @pact-foundation/pact-node jest
Enter fullscreen mode Exit fullscreen mode

Step 1: Define the Contract in the Consumer

Create a test file, consumer.test.js, where the consumer’s expectations are specified.

const { Pact } = require('@pact-foundation/pact');
const provider = new Pact({
  consumer: 'ConsumerApp',
  provider: 'ProviderService',
  port: 1234
});

describe('Pact with ProviderService', () => {
  beforeAll(() => provider.setup());
  afterAll(() => provider.finalize());

  test('should receive a valid response for a specific request', async () => {
    // Define consumer expectations here
    await provider.addInteraction({
      state: 'provider has valid data',
      uponReceiving: 'a request for information',
      withRequest: { method: 'GET', path: '/data' },
      willRespondWith: { status: 200, body: { id: 1, name: 'Test Data' } }
    });

    // Trigger the request and assert results
    const response = await fetch('http://localhost:1234/data');
    const data = await response.json();
    expect(data).toEqual({ id: 1, name: 'Test Data' });

    await provider.verify();
  });
});
Enter fullscreen mode Exit fullscreen mode

In this test, the consumer defines an expectation: when it sends a GET request to /data, it expects a 200 response with specific data.

Step 2: Publish the Contract

If you’re using a Pact Broker, you can publish the generated contract to share it with the provider.

npx pact publish ./pacts --consumer-app-version 1.0.0
Enter fullscreen mode Exit fullscreen mode

Step 3: Provider Verification

On the provider side, create tests that use the contract to verify compatibility. Here’s a simplified provider verification setup:

const { Verifier } = require('@pact-foundation/pact');

describe('Provider Verification', () => {
  test('validates contract with ConsumerApp', async () => {
    const opts = {
      providerBaseUrl: 'http://localhost:8080',
      // ...
    };
    await new Verifier(opts).verifyProvider();
  });
});
Enter fullscreen mode Exit fullscreen mode

This test verifies the provider against the consumer’s expectations, ensuring compatibility.

Conclusion

By using Pact, you can implement Consumer-Driven Contract Testing effectively, ensuring your services evolve in harmony. CDCT enables quick feedback on contract compliance, reduces integration errors, and fosters collaborative development between service teams.

Top comments (0)