Mock, Fake, or Stub Implementation¶
Test double — instantiates Representation-Independent Interface Contract
A lightweight stand-in that honors a component's interface but not its real behavior — an in-memory fake, a canned-response stub, or an expectation-checking mock — so clients can be built and tested without the real component.
A Mock, Fake, or Stub Implementation is a test double: an alternate implementation of the same contract, built deliberately light, that stands in for the real component while a client is developed and tested. Its distinctive contribution is being an implementation you fully control, placed on a spectrum from "reproduces real behavior" to "returns canned answers" — an in-memory fake that really works but simply, a stub that returns fixed responses to steer a client down a path, or a mock pre-loaded with expectations about the calls it should receive.[1] It exists only because the archetype's contract admits many implementations behind one surface — the double is another one, optimized for control rather than production. Where the Reference-Implementation Differential Test uses a trusted reference as an oracle, the double provides a convenient stand-in that itself must be kept honest.
Example¶
A checkout module depends on a UserRepository with loadUser and saveUser. Rather than run a real database in tests, the team writes an in-memory fake: a hash-map-backed UserRepository that honors the same contract — save then load returns the saved user; loading an unknown id returns not-found — but keeps everything in memory. The checkout logic now runs at full speed with no database, and can be written before the real repository even exists.
For one scenario they need a transient failure, so they add a stub that throws on the third saveUser call to exercise the retry path — a condition the real repository almost never produces on demand. For another, they use a mock to assert that a successful checkout calls saveUser exactly once. The business logic is developed and verified in isolation, and because the fake honors the same contract, code that passes against it should behave the same against the real repository — provided the fake is genuinely contract-conformant, which is the caveat the whole technique turns on.
How it works¶
- Pick the lightest double that answers the test's question — a dummy (unused placeholder), a stub (canned answers), a fake (a real but simplified working implementation), or a mock (pre-programmed call expectations that fail the test if unmet).
- Implement the same public surface as the real component, so the client cannot tell it is talking to a stand-in.
- Trade fidelity for control — decide how much real behavior to reproduce versus how much to hard-code or make injectable.
- Inject the awkward conditions — errors, timeouts, edge cases the real component rarely yields — that the client's handling needs exercised.
Tuning parameters¶
- Fidelity — how much real behavior the double reproduces, from a canned stub to a full in-memory fake. Higher fidelity catches more but costs more to build and can itself drift from the real thing.
- State versus interaction focus — a fake or stub checks the client's outputs given inputs; a mock checks the client's calls. Interaction checks are precise but couple the test to how the client uses the surface.
- Failure injection — how heavily the double is used to simulate errors, latency, and rare conditions the real component seldom produces on cue.
- Conformance level — whether the double is run against the same contract suite as the real implementation — the single guard against fake/real divergence.
- Lifespan — a throwaway per-test double versus a shared, maintained fake reused across the whole suite.
When it helps, and when it misleads¶
Its strength is decoupling client development and testing from the real component: fast, deterministic, able to simulate rare conditions, and available before the real implementation exists. Its failure modes all stem from the double being a second implementation. It can drift from the real contract, so tests pass against a fake that behaves unlike production — the deadliest failure, because it manufactures false confidence. Over-use of interaction mocks couples tests to a client's internal call pattern, so a harmless refactor breaks tests though no behavior changed. And a stub returning unrealistic data hides bugs behind tidy green runs. The classic misuse is asserting on interactions that are not part of the contract — that a method was called in a particular order — which turns a testing convenience into a straitjacket on the implementation. The discipline: run every double against the same Black-Box Contract Test Suite as the real implementation, and prefer state-based fakes over interaction mocks unless the interaction itself is the contract.
How it implements the components¶
This mechanism supplies an alternate, controllable implementation of the archetype's contract:
reference_implementation_anchor— the double is a stand-in implementation of the same contract, anchoring client development and tests where the real component is slow, costly, unbuilt, or hard to drive into a needed state.
It does not author the contract the double must honor (the Interface Definition Language, Design-by-Contract Clause, and Abstract Data Type Specification do), provide the oracle and acceptance gate that verify a double is contract-true (the Black-Box Contract Test Suite), or run a differential comparison against a trusted reference build (the Reference-Implementation Differential Test).
Related¶
- Instantiates: Representation-Independent Interface Contract — it is another implementation behind the same surface, built for control rather than production.
- Consumes: Interface Definition Language supplies the surface it implements; Black-Box Contract Test Suite keeps the double honest against the real contract.
- Sibling mechanisms: Black-Box Contract Test Suite · Reference-Implementation Differential Test · Interface Definition Language · Design-by-Contract Clause · Property-Based Conformance Test
Notes¶
A test double is only trustworthy if it is held to the same contract as the real implementation. An unverified fake is a second, silently diverging implementation masquerading as the first — so the cheapest way to make doubles safe is to run them through the same black-box contract suite the real component must pass.
References¶
[1] The taxonomy of test doubles — dummy, stub, spy, mock, and fake — is drawn from Gerard Meszaros's xUnit Test Patterns; Martin Fowler's "Mocks Aren't Stubs" popularized the state-versus-interaction distinction between fakes/stubs (checked by their results) and mocks (checked by the calls they receive). ↩