Prompt and scope
An order provider serves web, mobile, and asynchronous consumers. The team wants to catch breaking changes before releasing the provider, without starting every real service for each commit. Design a consumer-driven contract workflow: what consumers write, how providers verify, how a broker selects versions, how provider states work, and when deployment is allowed.
This tests API boundaries, test layering, version compatibility, and continuous delivery. Pact models a contract as the consumer’s required request and minimal response, then replays it against the provider; it does not replace unit, integration, or end-to-end tests.
What the interviewer is testing
- Whether consumer behavior becomes a minimal interaction contract instead of a copy of provider implementation.
- Whether you can connect mock consumer tests, provider verification, a broker, and a deployment matrix.
- Whether provider states isolate preconditions without shared-database ordering or production credentials.
- Whether you handle multiple consumer versions, unverified contracts, message contracts, and rollback.
Questions to clarify first
- Is the interface HTTP, asynchronous messaging, or both? The contract carrier differs.
- Which fields do consumers actually use? The contract should express required requests and minimal responses.
- Can provider states create, clean, and parameterize test data? Which dependencies need stubbing?
- How are versions identified, and which consumer/provider combinations must pass before production?
- Is there a broker, branch tagging, pending-pact policy, and rollback strategy?
A 30-second answer framework
Consumers write interaction tests against a Pact mock, producing a contract with only required request and response assertions; they publish it to a broker. A provider verifier selects target consumer versions, sets up provider states, replays requests in an isolated environment, and publishes results. The CI deployment gate checks the actual version matrix; a new unverified contract can be pending or block release. Contracts prove message shape and interaction, not all business correctness. On failure, stop deployment, fix the provider, or roll back to a version that passed the matrix.
Step-by-step answer
1. Define interactions from consumer behavior
Each interaction describes the method, path, required headers, important request fields, and minimal response assertions. Consumer tests call a Pact mock rather than a real provider, producing a fast, shareable contract tied to actual consumer use.
consumer test -> pact file -> broker
provider verifier + provider state -> replay -> verification result
deployment gate -> compatible version matrix -> deploy or block2. Keep the contract minimal and stable
Do not assert unused response fields, random IDs, or a complete database snapshot. Use matchers for types, formats, and required structure; validate only the shape of dynamic timestamps and UUIDs. Contract tests focus on communication messages, not generic provider functionality.
3. Design provider states
A provider state is an interaction precondition, such as “the order is paid.” A state handler creates or stubs data before verification and cleans it afterward. Parameters must be traceable and idempotent without production credentials; interactions should not depend on an uncontrolled sequence.
4. Manage versions and verification in a broker
Consumers publish contracts with branch, version, or environment labels. Providers verify selected consumer versions and publish results. The deployment gate checks the candidate provider against the consumers that will actually run, not merely whether “latest” is green. Pending behavior can let a new contract be verified and recorded before deciding whether to block.
5. Choose rollout order and compatibility windows
For a compatible change, deploy a provider that understands old requests and returns responses old consumers can read, then upgrade consumers. Breaking changes need dual reads/writes, a versioned path, or a migration window. Message pacts validate message ports, but real broker delivery, retries, and ordering still need separate tests.
6. Handle failure and observe production
Record the failed interaction, provider state, versions, commit SHA, and environment. Block deployment and roll back to the last version that passed the matrix; after release, watch 4xx/5xx, deserialization errors, dead letters, and business metrics. Green contract tests do not prove production correctness, so keep runtime protection.
High-quality sample answer
Each consumer would write real interactions against a Pact mock, generating a contract with only required requests and minimal responses and publishing it to a broker. The provider verifier selects consumer versions, runs repeatable provider states in isolation, replays requests, and publishes the result with provider version and commit SHA. The CI gate checks whether the consumer/provider versions that will run together have verification evidence; pending pacts allow a new contract to be verified without immediately breaking an old provider.
The contract covers communication shape and used fields, not all unit, integration, end-to-end, or business tests. Roll out readers before breaking writers: keep the provider compatible with old requests and responses, then migrate consumers; use versioned paths or a dual-write window for breaking changes. On failure, block release and return to the last passing matrix while retaining runtime error, dead-letter, and business metrics. Message pacts cover message content, while broker semantics need separate tests.
Common failure modes
- Making the contract a full provider response snapshot so unrelated fields block releases.
- Running only consumer mocks and never replaying the contract against the provider.
- Making provider states depend on shared database order, random data, or production credentials.
- Checking only the latest version and missing the real deployment matrix and long-tail clients.
- Treating Pact as end-to-end testing and ignoring real broker, authorization, performance, and business rules.
- Deploying after verification failure or lacking a verifiable rollback version.
Follow-up questions and reference answers
Why keep response expectations minimal?
Consumers should lock only fields they use. Minimal expectations reduce accidental coupling and let providers add unrelated fields safely.
How is a provider state different from a test fixture?
A provider state is an executable precondition interface that the verifier can set up and clean in the provider environment. A fixture is only a data artifact and may not establish cross-service state correctly.
What problem does a pending pact solve?
It lets a new contract enter the broker and be verified without immediately failing an old provider build the first time the contract appears unverified. Whether to enable it is an organizational release policy.
How do you prevent contract sprawl?
Deduplicate real consumer interactions, retire old versions, constrain random fields and full snapshots, and record owner, version, and last verification time in the broker.
Why does consumer version selection matter?
The gate must verify versions that will run together. Checking only main or latest can miss an older mobile or branch version still in production.
Can Pact prove provider business correctness?
No. It proves that interactions satisfy consumer contracts. Business invariants, performance, authorization, recovery, and real infrastructure still require other tests and production observation.