All topics
Testingintermediate

Mocking Functions and Modules

Replacing real dependencies with controlled fake implementations during tests to isolate the code under test and verify how it interacts with its dependencies.

Mocking replaces a real dependency — a function, a module, an API client — with a controlled, fake implementation during a test, letting you isolate the specific code you're actually testing from the behavior (and side effects, and slowness, and flakiness) of everything it depends on. This is essential for genuine unit testing, since a 'unit' test that actually reaches out to a real network or database on every run is slow, flaky, and no longer testing just the unit in isolation.

Mocking is like rehearsing a play with a stand-in prop gun instead of a real one — the actor still practices exactly the same motions and cues (the interaction/call pattern being verified) without any of the real risk, cost, or unpredictability a live prop would introduce, and the director can specifically check whether the actor pulled the trigger at the right moment, regardless of what a real gun would have actually done.

Key Concepts

1
Jest's jest.fn() creates a bare mock function that records how it was called (arguments, call count, return values) without needing any real implementation at all, useful for verifying that a callback was invoked with the expected arguments (expect(mockFn).toHaveBeenCalledWith(...)) without caring what it actually does. jest.fn(implementation) or mockFn.mockReturnValue(value)/mockFn.mockResolvedValue(value) let you additionally control exactly what the mock returns when called, which is how you simulate a dependency succeeding, failing, or returning specific test data without touching any real implementation.
jest.fn()expect(mockFn).toHaveBeenCalledWith(...)jest.fn(implementation)mockFn.mockReturnValue(value)mockFn.mockResolvedValue(value)
2
jest.mock('./module') replaces an entire imported module with an auto-mocked version (or a manually specified factory) for the duration of a test file, which is how you substitute a real API client, database layer, or other module-level dependency your code under test imports internally, without needing to restructure that code to accept the dependency as an explicit parameter (as dependency injection would require) — Jest's module mocking works by intercepting the module resolution system itself at the bundler/test-runner level.
jest.mock('./module')
3
A critical testing discipline that mocking specifically enables is verifying *interactions*, not just return values: asserting that a payment function was called exactly once with the correct amount, or that an error-logging function was called when an operation failed, are assertions about *how* your code used its dependencies, which is a different (and often more precise) kind of correctness check than simply asserting on a final return value, especially for code whose primary job is coordinating side effects rather than computing a pure result.