Fundamentals 10 min read

Classification and Best Practices for Test Doubles (Dumb, Fake, Stub, Mock)

The article explains the different types of test doubles—Dumb, Fake, Stub, and Mock—provides guidelines on when to prefer real implementations, discusses the drawbacks of overusing Stubs and Mocks, and offers practical advice for writing and maintaining Fakes in software testing.

Continuous Delivery 2.0
Continuous Delivery 2.0
Continuous Delivery 2.0
Classification and Best Practices for Test Doubles (Dumb, Fake, Stub, Mock)

This article, excerpted from Chapter 13 of *Google Software Engineering*, discusses the classification of test double objects and the principles and scenarios for their use.

Prefer using the real implementation whenever possible.

If the real implementation cannot be used in tests, a Fake is often the ideal solution.

Over‑using Stubs makes tests unclear and brittle.

When feasible, avoid Mocks because they expose implementation details and lead to fragile tests.

Classification of Test Doubles

Dumb (placeholder): provides no value in tests.

Fake: a lightweight implementation such as an in‑memory database.

Stub: hard‑coded return values created with a mocking framework.

Mock: used for interaction testing, typically to verify that a method was called.

Prefer Realism Over Isolation

Real implementations give higher confidence that the system works correctly. Relying heavily on test doubles forces engineers to run integration tests or manual verification, which slows development and can let bugs slip through.

When to Use Real Implementation Code

If the real code is fast, deterministic, and has simple dependencies, it should be the first choice. In practice, consider execution time, determinism (e.g., random numbers), and the cost of constructing dependencies.

Using Fakes – Considerations

Creating a Fake requires domain expertise because its behavior must mimic the real implementation, and it must be maintained whenever the real behavior changes. Teams should weigh the productivity gain against the maintenance cost; a Fake is worthwhile when many users benefit.

Fakes themselves must have tests to ensure they stay aligned with the real API.

Risks of Overusing Stubs

Tests become unclear because extra code is needed to define stub behavior, making it hard to understand without deep knowledge of the system.

Tests become brittle as stubs expose implementation details; any change in production code requires updating the stub.

Tests become less effective because stubs cannot guarantee that the stubbed function behaves like the real one. Example:

when(stubCalculator.add(1, 2)).thenReturn(3);

If the contract of add() changes, the stub will no longer be faithful.

When to Use Stubs

Use only a small number of Stubs; many stubs indicate either over‑use or that the system under test is too complex and needs refactoring. Even when a Stub is appropriate, prefer a real implementation or a Fake.

Mocks – Use Sparingly

Prefer state testing over interaction testing. State tests call the system and verify returned values or side‑effects, while interaction tests expose implementation details and make tests fragile.

Interaction testing is appropriate only when state testing is impossible (e.g., real implementation is too slow) or when verifying call counts or order is essential, such as ensuring a cache limits database accesses:

verify(databaseReader, atMostOnce()).selectRecords();

Even then, supplement with larger‑scope state tests.

Best Practices for Interaction Testing

(1) Test only functions that cause state changes.

(2) Avoid over‑specification; test behavior rather than individual methods or classes.

Illustration:

Conclusion

Test doubles are crucial for fast, reliable testing, but misuse can make tests unclear, brittle, and less effective. Engineers should prioritize real implementations, use Fakes when necessary, limit Stubs, and avoid Mocks unless interaction testing is truly required.

Key takeaways:

Prefer real implementations over test doubles.

If real code cannot be used, a Fake is often the best alternative.

Overusing Stubs leads to unclear and fragile tests.

Avoid Mocks when possible, as they expose implementation details.

testingsoftware engineeringUnit TestingmockingTest Doublesfakesstubs
Continuous Delivery 2.0
Written by

Continuous Delivery 2.0

Tech and case studies on organizational management, team management, and engineering efficiency

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.