Test Doubles: Stubs vs. Mocks vs. Fakes vs. Spies
This article covers the fundamentals of test doubles – including exam-style questions and key takeaways.
In a Nutshell
- Stub: returns predefined answers
- Mock: verifies interactions (expectations)
- Fake: simplified, working implementation
- Spy: records calls for later verification (combines stub + mock)
Core Definitions
Stub
Returns fixed answers without checking behavior. Useful for stateless tests where you just need predictable return values.
Mock
Verifies that specific methods are called with specific parameters. Essential when interactions between components matter.
Fake
A working but simplified implementation (like an in-memory database). Great for tests that need realistic behavior without external dependencies.
Spy
Records method calls and allows verification after the fact. Bridges stub and mock by supporting both preset returns and call tracking.
Key Points for Study
- Stub: predefined answers, no behavior verification
- Mock: define and verify expectations
- Fake: functional simplification (e.g., in-memory repository)
- Spy: record calls, verify later
- When to use each: stubs for state, mocks for behavior, fakes for complexity
- Common frameworks: Mockito, unittest.mock, Jest
Core Components
- Stub (answers)
- Mock (expectations)
- Fake (simplified implementation)
- Spy (recording)
- Test isolation
- Framework usage
- Setup/teardown
- Assertions
- Verification
- Maintenance
Practical Example (Discount Service)
// Stub
DiscountPolicy stub = new DiscountPolicyStub(10); // always 10%
int rabatt = service.berechneRabatt(kunde, artikel);
// Mock
DiscountPolicy mock = mock(DiscountPolicy.class);
when(mock.getRabatt(kunde)).thenReturn(10);
verify(mock).getRabatt(kunde);
// Fake
InMemoryDiscountRepository fake = new InMemoryDiscountRepository();
fake.add(new Discount(kunde, 10));
// Spy
DiscountPolicySpy spy = new DiscountPolicySpy();
service.berechneRabatt(kunde, artikel);
assertEquals(1, spy.getCallCount());
Common Exam Questions (Quick Answers)
- Difference between stub and mock? A stub returns answers; a mock verifies calls were made.
- When should you use a fake? When you need a functional simplification, like an in-memory database.
- What does a spy do? It records method calls and lets you verify them after execution.
Essential References
- https://martinfowler.com/articles/mocksArentStubs.html
- https://junit.org/junit5/docs/current/user-guide/
- https://testing.googleblog.com



