Contract Testing vs Integration Testing: What's the Difference?
Learn the difference between contract testing and integration testing, how each approach works, when to use them, and why modern teams often use both together.
Contract tests and integration tests both examine boundaries between software components, but they answer different questions.
A contract test checks whether a provider still satisfies an interface expected by a consumer. An integration test runs connected components together to verify that their interaction actually works.
For an account API:
contract test
consumer expectation ↔ provider interface
integration test
client → API → database
Most systems benefit from both because interface compatibility and working infrastructure are separate failure modes.
Contract Tests Check Compatibility at a Boundary
Suppose a client expects:
{
"id": 123,
"name": "Sarah Smith",
"status": "active"
}
A contract can describe the parts of that interaction the consumer depends on: request shape, response fields, status, headers, types, or message content.
If the provider removes status or changes its type incompatibly,
provider verification can fail before the changed service reaches an
environment shared with the consumer.
The test is about the agreement at the boundary. It does not need to prove that every dependency behind the provider is working.
Integration Tests Run Real Components Together
An integration test exercises an actual interaction between components.
For example:
test client
↓
account API
↓
database
The test might verify that the API accepts the request, queries the database, maps the result, and returns a response the client can process.
The exact amount of “real” infrastructure varies. An integration test can run two services with a test database, one service with a real database container, or a larger environment. What makes it an integration test is that connected components are exercised together rather than only checking an interface description.
Consumer-Driven Contracts Record What a Consumer Needs
In consumer-driven contract testing, the consumer records the interactions it relies on and the provider verifies those expectations.
consumer
↓
expected interaction
↓
contract
↓
provider verification
This is the model popularized by tools such as Pact.
The contract should describe meaningful consumer expectations rather than reproducing every field the provider happens to return. Overly broad contracts can make harmless provider changes look breaking.
Compare the Failures Each Test Detects
Assume the provider changes:
{
"customerName": "Sarah"
}
to:
{
"name": "Sarah"
}
If a consumer contract requires customerName, provider verification
should fail.
An integration test catches the same change only if its assertions exercise the affected consumer behaviour. A broad “request returned 200” integration test may pass even though the client can no longer read the expected field.
Now consider a different failure:
API contract is unchanged
database credentials are wrong
Contract verification can still pass because the interface agreement has not changed. An integration test that uses the database can expose the configuration failure.
Each failure exercises a different part of the test suite.
Contract Tests Can Give Early Compatibility Feedback
Contract verification can often run without starting the consumer, provider dependencies, and a complete shared environment at the same time.
That makes it suitable for CI checks on service changes.
Typical strengths include:
detect incompatible interface changes early
give provider teams consumer-specific feedback
reduce dependence on shared test environments
support independently deployed services
Contract tests still require maintenance. Contracts can become stale, consumers can publish overly broad expectations, and verification infrastructure can be misconfigured.
Integration Tests Cover Behaviour the Contract Does Not
Integration tests can expose problems involving:
database behaviour
authentication and authorization
serialization configuration
network or protocol setup
dependency wiring
transaction behaviour
real client libraries
external-service adapters
A contract test may validate the expected HTTP response shape without proving that the provider can obtain the underlying data.
Database, authentication, configuration, and other runtime failures still require tests that exercise those integrations.
Contract Testing Is Not Limited to Microservices
Microservices make contract testing attractive because independently deployed services create many compatibility boundaries.
The same technique can be useful between:
web frontend and backend
mobile application and API
internal platform and client
service and partner API
message producer and consumer
Contract testing is useful when independently owned or released components need an explicit compatibility check.
Compare the Two by Failure Type
| Failure | Contract test | Integration test |
|---|---|---|
| Provider removes a required response field | Strong fit | Only if asserted by the test |
| Provider changes a field type incompatibly | Strong fit | Only if exercised and asserted |
| Database credentials are wrong | Outside contract scope | Strong fit |
| Authentication wiring is broken | Usually outside contract scope | Strong fit |
| Consumer depends on an undocumented field | Can expose when captured in the contract | Depends on test coverage |
| Network/configuration between real components fails | Outside contract scope | Strong fit |
“Contract testing is fast; integration testing is slow” is too broad to be a definition. Runtime depends on the test design and environment. The useful distinction is the risk each test is intended to detect.
Keep Integration Tests Focused
Using contract tests can reduce the need to duplicate every interface-shape assertion in a large end-to-end environment.
Integration tests can then concentrate on boundaries where running real components provides additional evidence:
database persistence
authentication flow
message delivery
framework configuration
critical service-to-service paths
third-party adapters
This usually produces a more useful test suite than trying to prove every compatibility rule only through a shared environment.
Use Both Where Both Risks Matter
A practical pipeline might contain:
unit tests
↓
contract verification
↓
focused integration tests
↓
selected end-to-end tests
That ordering is not mandatory. Teams can run tests in parallel or arrange them around deployment architecture and feedback time.
Contract tests verify compatibility promises. Integration tests verify selected interactions between connected components. Choose coverage according to the failures the system needs to detect.
More Articles Like This

What Is a Mock Server, and When Should You Use One Instead of a Real Backend?
What Is Playwright? Browser Testing and Automation Explained

How to Mock an API Before the Backend Exists
What Is Visual Regression Testing?
