ASP.NET - Contract Testing (Pact) in ASP.NET – Detailed Explanation

Contract testing is a testing approach used in distributed systems, especially in microservices architectures, to ensure that two services can communicate with each other correctly. Instead of testing the entire system end-to-end, contract testing focuses on the agreement (or “contract”) between a service provider (API) and a service consumer (client).


1. What is Contract Testing?

In a typical ASP.NET application, especially when using microservices, multiple services interact via APIs. Contract testing verifies that:

  • The consumer sends requests in the expected format

  • The provider responds with the expected structure and data

This “contract” defines:

  • Request format (URL, headers, body)

  • Response format (status code, JSON structure, data types)

If either side changes without updating the contract, the system can break. Contract testing prevents this.


2. Why Contract Testing is Important

Traditional testing approaches have limitations:

  • Unit testing only tests isolated components

  • Integration testing can be slow and complex

  • End-to-end testing is brittle and expensive

Contract testing provides a balance by:

  • Catching integration issues early

  • Reducing dependency on full system availability

  • Allowing teams to work independently

It is especially useful in:

  • Microservices architectures

  • API-driven development

  • Teams working on separate services


3. Consumer-Driven Contracts

Pact follows a consumer-driven contract approach.

This means:

  • The consumer defines expectations

  • The provider must satisfy them

Example Scenario

Consumer expects:

  • Endpoint: /api/orders/1

  • Method: GET

  • Response:

    • Status: 200

    • JSON:
      {
      "id": 1,
      "status": "shipped"
      }

This expectation is saved as a contract file (JSON).


4. How Pact Works

Pact involves two main phases:

Step 1: Consumer Test (Contract Creation)

  • The consumer writes tests using Pact

  • A mock server simulates the provider

  • Expected interactions are recorded

  • A contract file is generated

Example flow:

  • Consumer sends request to mock server

  • Mock server validates request

  • Returns predefined response

  • Pact saves interaction as contract


Step 2: Provider Verification

  • The provider loads the contract file

  • Tests are run against the real API

  • Verifies if actual responses match expectations

If the provider does not meet the contract:

  • The test fails

  • Developers are alerted before deployment


5. Pact in ASP.NET Core

To use Pact in ASP.NET:

Required Libraries

  • PactNet (for .NET applications)

Consumer Example (Simplified)

var pact = Pact.V3("ConsumerService", "ProviderService", new PactConfig());

await pact.WithHttpInteractions(async builder =>
{
    builder
        .UponReceiving("A request for order")
        .WithRequest(HttpMethod.Get, "/api/orders/1")
        .WillRespond()
        .WithStatus(HttpStatusCode.OK)
        .WithJsonBody(new { id = 1, status = "shipped" });
});

This creates a contract file after execution.


Provider Verification Example

var verifier = new PactVerifier("ProviderService");

verifier
    .WithHttpEndpoint(new Uri("https://localhost:5001"))
    .WithFileSource(new FileInfo("pact.json"))
    .Verify();

This ensures the API complies with the contract.


6. Pact Broker

In real-world systems, contracts are shared using a Pact Broker.

It acts as:

  • A central repository for contracts

  • A versioning system for API agreements

  • A coordination tool between teams

Benefits:

  • Tracks compatibility between services

  • Helps in safe deployments

  • Enables continuous integration workflows


7. Advantages of Contract Testing

  • Detects breaking API changes early

  • Reduces reliance on full integration environments

  • Enables parallel development across teams

  • Improves API reliability

  • Faster feedback compared to end-to-end tests


8. Limitations

  • Does not replace end-to-end testing completely

  • Requires discipline in maintaining contracts

  • Only tests defined interactions, not unexpected cases

  • Initial setup can be complex


9. When to Use Contract Testing

Use Pact in ASP.NET when:

  • You are building microservices

  • Multiple teams consume your APIs

  • APIs change frequently

  • You want to avoid integration failures in production

Avoid relying solely on it for:

  • UI testing

  • Complex business workflows


10. Best Practices

  • Keep contracts small and focused

  • Avoid over-specifying responses

  • Automate contract verification in CI/CD

  • Version contracts properly

  • Use a Pact Broker for team collaboration


Conclusion

Contract testing using Pact is a powerful approach to ensure reliable communication between services in ASP.NET applications. By focusing on the agreement between consumer and provider, it reduces integration risks, enables independent development, and improves system stability. It is particularly valuable in modern architectures where APIs form the backbone of communication.