Difference between jest.fn, jest.spyOn, and jest.mock in React

Tests whether you distinguish Jest's three mocking scopes. Good answers: jest.fn for standalone callbacks; jest.spyOn to observe existing methods; jest.mock to swap entire modules. Red flag: using them interchangeably or saying spyOn replaces modules.
What's really being asked
This question tests whether you understand scope, granularity, and side effects across Jest's three primary mocking mechanisms. Senior engineers should know when to replace a single function, observe an existing method, or swap an entire module, and they should understand hoisting and cleanup implications in a React testing environment.
The full answer
Four distinctions in order. First, jest.fn creates a brand new mock function from scratch, useful for callbacks passed as props or standalone utilities. Second, jest.spyOn wraps an existing method on an object or module, letting you observe calls while usually preserving the original implementation unless you override it. Third, jest.mock operates at the module level, replacing an entire import before the test runs and hoisting above imports so it cannot be called mid-test inside a describe block. Fourth, practical React scenarios: use jest.fn for event handlers like onSubmit to assert they were called with correct arguments; use jest.spyOn to verify that a method on a class instance or a imported named function was invoked without stopping its real behavior; use jest.mock to stub out a heavy child component, a custom hook, or an API client module so the test does not render or fetch real data.
The mistakes people make
Saying jest.spyOn replaces the entire module or that it permanently mutates the original function across tests. Claiming jest.mock can be called inside a test block to target one function, which ignores hoisting rules. Asserting that jest.fn is the only tool needed because you can just pass it everywhere, which misses module-level isolation. Forgetting to restore or clear mocks between tests, leading to leaked state. Confusing spyOn with mock on default exports, which requires different syntax and understanding of module factories.
What usually comes next
How do you mock a React hook or a child component without breaking prop types? What is the difference between mockReturnValue and mockImplementation, and when would you use one over the other? How do you handle cleanup if a spy overrides the original implementation? Explain how Jest hoisting affects imports and why jest.mock must reference variables outside the factory function. How would you test a module that exports both named and default exports?
A concrete example
Imagine a LoginForm component that imports validateEmail from utils and calls an onSubmit prop. Use jest.fn to create the onSubmit prop and assert it receives form data. Use jest.spyOn on the utils module to track validateEmail calls while still running the real validation logic. Use jest.mock to replace the entire analytics module that tracks login events, because you do not want to fire real analytics in unit tests and the module is imported at the top of the file.
Interview question
To stub a heavy imported child component while tracking calls to a real imported utility function, which tool combination should you use?
- a.jest.spyOn for the component and jest.fn for the utility
- b.jest.fn for the component and jest.spyOn for the utility
- c.jest.mock for both the component and the utility
- d.jest.mock for the component and jest.spyOn for the utilityCorrect
Why? this is the answer
The card pairs jest.mock with replacing an entire module like a child component import, and jest.spyOn with observing an existing method while preserving its real behavior. Option C is tempting because jest.mock does replace modules, but applying it to the utility would strip the real implementation you still want to run.
Just read this? Test yourself on what you have been reading.
Read the original → jestjs.io
- #jest
- #mocking
- #react
- #testing
- #javascript
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
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. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles