Mocking and the Main Test Doubles
What is mocking in testing, and how do mocks differ from stubs, spies, and fakes? When would you use each?
what they're testing: The interviewer is probing whether you can isolate a unit deliberately and choose a substitute without making the test brittle or misleading.
Mocking means replacing a real collaborator, such as a database client, network service, or clock, with something the test controls. That substitute is a test double. People often use "mock" for any test double, but the narrower terms describe different roles.
A stub returns configured values or errors to drive the code down a chosen path. A mock is also configured for the test, but the test verifies expected interactions, such as whether a method received particular arguments.
A spy records calls to a function or object. Depending on the framework and configuration, it may call the real implementation or use a replacement. A fake is a lightweight working implementation, such as an in-memory repository, built for tests rather than production.
Choose the double that matches the question. Use a stub to control an input, a mock or spy when a call itself is part of the behavior, and a fake when tests need a usable implementation. Doubles can make tests faster and more deterministic, but they do not prove the production integration works. Prefer observable outcomes when they express the behavior clearly, and keep integration coverage for real boundaries.
Where people slip
the tempting wrong answer, and what's actually true
Mocks, stubs, spies, and fakes are interchangeable names for the same thing.
They are all test doubles, but the names describe different roles: stubs control responses, mocks carry interaction expectations, spies record calls, and fakes provide working test-oriented implementations.
A spy always calls the real implementation, so it cannot alter behavior.
A spy records calls; whether it calls through or uses a replacement implementation depends on the framework and configuration.
If unit tests pass with a fake database, the production database integration is covered.
A fake can behave differently from the production dependency, so separate integration tests must exercise the real boundary.
If they push further
When should you avoid mocking?
Use the real collaborator when it is fast, deterministic, and easy to construct; avoid interaction checks when an observable result expresses the behavior more clearly.
What makes an over-mocked test brittle?
It verifies internal call sequences rather than a stable outcome, so a harmless refactor can break the test without changing behavior.
How do you keep a test double aligned with the real dependency?
Keep the contract small, run contract or integration tests against the real implementation, and use framework-supported fakes where available.
Sources
- Android Developers: Use test doubles in Android ↗developer.android.com
- Jest: Mock Functions ↗jestjs.io
- Python: unittest.mock ↗docs.python.org
- Microsoft Learn: Best practices for writing unit tests ↗learn.microsoft.com
Now answer it yourself.
Reading a strong answer is easy. Producing one under pressure is the skill the interview tests. Gapmap grades your answer against the same bar an interviewer would.
beta
The interviewer part is in the works.
The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.