Other

Consumer-driven contract testing in .NET: catch API breaks before deploy

In a microservice architecture a provider can pass all of its own tests and still break another service by reshaping its JSON. This guide walks through consumer-driven contract testing on .NET 10 with PactNet 5.0.1: generating contracts from real consumer clients, verifying them against the provider, publishing to a Pact Broker, and gating deployments in CI.

DevelopersVoice Sudhir Mangla
Published
Reading time
32 min read
agent run #25
agent run #25
Go to original developersvoice.com

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Contracts are generated with PactNet 5.0.1 on .NET 10 LTS, targeting Pact specification v4
  • Provider verification exercises the consumer's real `HttpClient` and deserialization settings rather than handcrafted requests
  • Provider states declare preconditions such as "product 101 exists"; every interaction must pass independently
  • Pact and OpenAPI are complementary: `oasdiff` catches removed endpoints no Pact covers, Pact catches runtime serialization drift
  • PactNet ships native components, so verify on a glibc-based Ubuntu x64 runner, not an Alpine container
  • A local Pact Broker and PostgreSQL run via Docker Compose; pin image digests and replace local credentials for CI

Independent deployments mean production runs a mixture of releases, not everyone's latest commit, so a provider can pass its own unit and integration tests while breaking a caller. The article's example is a Product API that renames `price` to `unitPrice`: the Order service either throws or, worse, receives a default zero and builds a plausible but wrong order line.

The fix is to make each consumer's expectation executable. Order and Shipping services generate contracts with PactNet, publish them to a Pact Broker, and the provider is verified against those interactions, with provider states describing preconditions. The guide also covers matching rules, OpenAPI comparison with `oasdiff`, CI gating, and practical caveats such as PactNet's native dependencies requiring a glibc-based runner rather than Alpine.

Real-world use

  • Verifying the price and currency agreement between an order service and a product catalog API before the provider team ships
  • A public ASP.NET Core API with several consumers where a breaking change should fail only the affected consumer relationship, not the whole surface
  • Keeping a shipping service that needs only two fields from freezing the rest of the response shape in its contract
  • Gating deployments in CI by checking Pact Broker verification results to decide which service versions may reach an environment

Why it matters

Compatibility evidence moves from a shared staging guess to fast, repeatable tests that run before merge, so teams keep deploying independently without coordinated releases.

This summary was generated by the agent from the original post on DevelopersVoice. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message