Test Doubles: Mocks, Stubs, and Spies
A test double is a stand-in for a real component, letting you test code in isolation. Use them to fake slow dependencies like database calls or external APIs, making tests fast and predictable.
Why it exists
To test a unit of code without its real dependencies. Real dependencies like databases or network APIs are often slow, non-deterministic, or have side effects like writing data. This makes automated tests unreliable and difficult to run. Test doubles solve this by providing predictable stand-ins.
The mental model
Think of a test double as a stunt double in a movie. You want to test the main actor's dialogue (your unit of code), not their ability to survive a real explosion (the database connection). The stunt double (test double) stands in for the dangerous or complex part (the dependency), so you can safely and quickly test what you actually care about.
How it works
Test doubles are objects or functions that mimic the interface of a real dependency. The main types differ in how they behave and what you verify. First, Stubs provide canned answers to calls made during the test; for example, a user repository stub might always return a specific user object. Second, Mocks are objects that register which calls they receive, with pre-defined expectations you verify after the test. Third, Spies are like stubs but also record information about how they were called, letting you make assertions after the fact without setting up prior expectations.
When to use it
Use test doubles to isolate the code under test from its dependencies, which is the core of unit testing. Use stubs for providing state (e.g., returning a record from a fake database). Use mocks for verifying interactions (e.g., ensuring an email service was called). Use spies when you need to check interactions without the rigid expectations of a mock.
When not to use it
Avoid test doubles in integration tests, where the goal is to verify that multiple real components work together correctly. Overusing mocks in unit tests is a major footgun; if your test just mirrors your implementation logic, it becomes brittle and resistant to refactoring. A good test verifies behavior, not the exact sequence of internal function calls.
One canonical example
In a Node.js Express app, you might test a UserService that depends on a UserRepository. To unit test the createUser method, you would provide a stub for UserRepository.save that simply returns a predictable user object. This allows you to test the service's logic without hitting a real database.
Interview question
When would you use a Mock over a Stub or Spy?
- a.When you need to verify that a specific interaction with a dependency occurred as expected.Correct
- b.When you need to record all calls to a dependency for later inspection without prior expectations.
- c.When you need to provide a predictable return value for a dependency.
- d.When you want to replace a complex dependency with a simpler, in-memory version.
Why? this is the answer
Mocks are specifically used for verifying interactions with dependencies, often with pre-defined expectations about how they should be called. While Spies also record calls for later inspection, Mocks are designed for direct verification of expected interactions, making option A the correct choice. Option B describes the primary use case for a Spy.
Just read this? Test yourself on what you have been reading.
Read the original → en.wikipedia.org
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on testing — each one lists the topics its interview covers.
See open roles