← Concepts

阅读中文版本

Test Double

A test double is any stand-in used in place of a real dependency during a test: a stub, fake, spy, or mock.

testing

Definition

A test double replaces a real collaborator so a unit can be tested in isolation. The variants differ by what they assert: a dummy is passed but never used; a stub returns canned answers; a spy records calls for later inspection; a fake is a lightweight working implementation; a mock is pre-programmed with expectations and fails if they are not met. Choosing the right kind, and how much to mock, determines whether tests catch real defects or merely restate the implementation.

Context and scope

Used in unit tests to remove slow, flaky, or external dependencies such as databases, networks, clocks, and third-party APIs.

Common misconceptions

  • All doubles are mocks — mock is one variant with expectations; stub, spy, and fake serve different purposes
  • More mocking is better isolation — over-mocking couples tests to implementation, so refactors break tests while real bugs pass
  • Fakes and mocks are interchangeable — a fake has working behaviour, so it can be shared and is often less brittle than expectation-laden mocks

Anti-patterns

  • Mocking the very unit under test, so the test verifies the mock and not the code
  • Asserting every internal call, turning tests into a mirror of the implementation
  • Never using a real or in-memory database when that would exercise far more of the integration

Related concepts

Related examples

Authoritative source

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

What it is

A test double is any object that stands in for a real dependency. A stub answers queries with fixed data; a fake is a simplified but working implementation, such as an in-memory repository; a spy records interactions for later assertions; a mock is set up with expectations and reports whether they were satisfied. Each exists to remove a dependency from the test — a database, a clock, a remote API — so the code under test can run fast and deterministically.

Why it matters

Real dependencies make tests slow, flaky, and dependent on external state; doubles restore speed and repeatability. But the choice of double shapes what the test can find. A stub lets code follow an error path that is hard to trigger. A fake exercises real logic. A mock asserts interactions, which is powerful when the interaction is the contract and fragile when it is merely an implementation detail.

How to use it well

Prefer the least assuming double that works: use a stub to provide data, a fake to exercise logic, and reserve mocks for collaborations that truly are the observable behaviour. Never mock the unit under test, and keep doubles at the edges of your design so tests stay about behaviour rather than structure. When a real integration is the point, test against a real or in-memory component instead of a mock, and verify the double honours the same contract as the real thing.