← Concepts

阅读中文版本

Integration Testing

Integration testing exercises real components together, including databases, queues, and HTTP boundaries, to verify the wiring that unit tests deliberately fake.

testing

Definition

Integration testing verifies that separately developed components work together through their real interfaces and infrastructure rather than through test doubles.

Context and scope

Applied at service boundaries, persistence layers, message flows, and frontend-to-API seams where serialization, configuration, and transactions matter.

Common misconceptions

  • Integration testing means running the entire system end to end
  • Contract tests make integration tests unnecessary
  • Any test that touches a database is automatically a good integration test

Anti-patterns

  • Spinning up every service for each test and calling the result integration coverage
  • Sharing one mutable database across tests without isolation or cleanup
  • Asserting only that a request returned 200 while ignoring stored state

Related concepts

Related examples

Authoritative source

https://martinfowler.com/bliki/IntegrationTest.html

What it verifies

An integration test exercises two or more real components through their actual interfaces: an application and a database, a producer and a broker, a browser and an API. Unit tests replace these collaborators with doubles, so they cannot reveal a wrong column type, a missing migration, a misconfigured queue name, or a serialization mismatch. Integration testing exists to catch exactly those wiring defects.

Narrow versus broad

Broad integration tests launch many services and approximate production, but they are slow and failures are hard to localize. Narrow tests keep the boundary small: one service plus its real database, or one consumer plus a real broker. Compared to end-to-end tests, narrow integration tests run faster and point at the broken seam. Most teams need many narrow tests and only a few broad journeys.

Contract tests are not enough

A contract test proves that a consumer’s expectations match a provider’s interface. It does not prove the provider can reach its database, that credentials work, or that the transaction commits. Keep contract tests for interface drift and integration tests for real infrastructure behavior.

Practical guidance

Provision dependencies with containers or ephemeral environments, isolate data per test, and reset state between runs. Seed realistic fixtures rather than empty schemas. Assert on persisted state and emitted messages, not only response codes. Run integration tests on every pull request if they finish in minutes; otherwise stage them before merge or deploy.

Trade-offs

Integration tests cost infrastructure, time, and maintenance. They are also where flakiness concentrates, so treat unstable tests as defects. For example, a suite that retries three times before passing hides a race in the code or the test harness. Use them where configuration and real protocols create risk, and keep the rest fast.