Test double
The umbrella word for any fake you swap in for a real dependency in a test: stubs, spies, mocks, fakes, dummies.
See it
What it is
Test double is the umbrella term for anything you swap in where the real dependency would go. The metaphor is the stunt double, and the taxonomy comes from Gerard Meszaros's 'xUnit Test Patterns'. Five flavors: dummy (filler passed to satisfy a signature, never used), stub (returns canned answers), spy (records how it was called), mock (preloaded with expectations and verifies them), and fake (a real but lightweight implementation, like an in-memory repository or SQLite standing in for Postgres). That is the book. Framework vocabulary is looser: 'vi.fn()' and 'jest.fn()' get called mocks whether or not any expectation is attached, and plenty of teams say 'mock' for every row in the list. Use the precise word when the distinction matters and let the loose one go when it does not.
You reach for one when the real collaborator is slow, costs money, is unreliable, or has effects you can't take back: Stripe charges, outbound email, the system clock, a third-party API with rate limits. The best place to put the double is the boundary you own, so intercept the HTTP layer (MSW, nock, VCR-style recorded cassettes) rather than reaching into your own modules and reassigning their internals.
The misconception worth internalizing: a double tests your assumption about the collaborator, not the collaborator. Suites full of doubles go green while production is broken, because the real API renamed a field last month. That gap is exactly what integration tests and contract tests exist to close, which is also why the old advice says do not mock types you do not own.
Ask AI for it
Introduce test doubles for the external dependencies in this module so the unit tests never touch the network, the clock, or the payment provider. Put the seam at the boundary: define an interface for each dependency, inject it through the constructor or a parameter with the real implementation as the default, and supply a fake in tests. Use a stub where the test only needs a canned value, a spy where it needs to verify a side effect happened, and an in-memory fake for the data store. Freeze the clock with a fixed date, and leave one integration test that runs against the real thing.