Testing

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 Testing vs Integration Testing: What's the Difference?

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

FailureContract testIntegration test
Provider removes a required response fieldStrong fitOnly if asserted by the test
Provider changes a field type incompatiblyStrong fitOnly if exercised and asserted
Database credentials are wrongOutside contract scopeStrong fit
Authentication wiring is brokenUsually outside contract scopeStrong fit
Consumer depends on an undocumented fieldCan expose when captured in the contractDepends on test coverage
Network/configuration between real components failsOutside contract scopeStrong 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.

Top