Test Doubles
A track of P30 · Testing & Mocking.
Mocks and patching without the cargo cult: build a recording Mock and the patch swap-and-restore by hand, then double only the boundaries you don't own - network, time, payments - and run your own code for real.
Some collaborators cannot appear in a unit test. You will not charge a real
card to check your checkout maths, call a live email server, or let the wall
clock decide whether "expires tomorrow" is true. A test double stands in for
them: a stunt actor that takes the dependency's place, plays the line you need,
and - crucially - records how it was used so you can assert the interaction
afterwards. unittest.mock gives you Mock for the stand-in and patch for
the swap; this track builds tiny versions of both so neither is magic.
The mechanics are humbler than the reputation. A mock is an object that records
every call and returns whatever you configured - you will write one whose
.calls, .call_count and assert_called_with come from a plain list. patch
is setattr(obj, name, double) with the original saved and restored on exit -
which is exactly why the notorious rule holds: you patch a name where it is
used, not where it is defined, because you are rebinding an attribute on the
object that does the lookup. Build the swap-and-restore and that rule stops
being a mantra and becomes obvious.
The hard part is not the tools but the restraint. Every mock removes real code from the test, so a suite that mocks everything is green and proves nothing - it asserts its own setup and shatters on the first refactor. The track closes on judgement: mock only the edges you do not own or cannot run - network, time, randomness, payments - and let the code you actually wrote run for real. A mock standing in for your own logic means you are testing the mock.