Quiz
Warm-up from lesson 4-3: a user reports a bug. What does the TDD-flavored bug-fix habit say to write before touching the code?
The unit and its noisy neighbors
A unit test checks one small piece of code, the unit, in isolation. But real functions have dependencies: they call the network, read the clock, query a database, or roll random numbers. Those neighbors poison tests in three ways:
- slow: a real API call takes seconds, and you want thousands of tests per minute
- flaky: the network can fail even when your logic is perfect, so the test lies
- nondeterministic: the clock and random values change every run, so there is no fixed expected value to assert
The cure is a test double: a stand-in object or function that plays the dependency's role during the test, like a stunt double in a film. Your logic runs for real, the neighbors are actors.
The three doubles you will actually meet
People use mock loosely for all of these, but the distinctions matter:
- a stub returns canned answers. It exists so the unit has data to work with: a
fetch_tempthat always says 35 - a fake is a real but lightweight implementation: an in-memory dictionary standing in for a database
- a mock records how it was called so the test can assert on the interaction afterward: "was
send_emailcalled once, with this address?"
Rule of thumb: use a stub when you care about what the unit returns, a mock when you care about what the unit does to the outside world, and a fake when the unit needs a dependency that genuinely works.
Quiz
You are testing charge_customer, and the important question is whether it calls the payment gateway exactly once with the right amount. Which double fits?
Quiz
A test that calls the real network fails about once a week even though the code under test is correct. Teammates start shrugging at red runs. What is the deepest cost of keeping that test as-is?