Jest · Unit tests that survive refactors
When do you use jest.fn versus jest.spyOn?
Short answer
jest.fn creates a new mock with no original behaviour. jest.spyOn wraps an existing method, observes calls and can temporarily replace its implementation. Use a spy when the original object already exists.
The difference is what you start with. A mock function is a blank replacement you inject. A spy is attached to a real object or module method, so it preserves the relationship to that object and can call through to the original implementation.
const spy = jest.spyOn(storage, "getItem");
storage.getItem("token");
expect(spy).toHaveBeenCalledWith("token");
spy.mockRestore();
const callback = jest.fn().mockReturnValue(42);
expect(handler(callback)).toBe(42);Choosing between them
- Use
jest.fnfor a callback, constructor argument or injected dependency - Use
jest.spyOnto observe a real method without replacing it - Add
.mockImplementationto a spy when you need to override the original - Call
spy.mockRestore()orjest.restoreAllMocks()to undo the wrap
Spying on a module export is not always possible with native ES modules because the binding is read-only from the importing side. In that case, mock the module with jest.mock and a factory instead of trying to patch the export. With CommonJS, spies on the module object usually work.
restoreMocks: true in the Jest config or restore in afterEach so the next test sees the real method.Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1Why can spying on an ESM export fail?
- 2What does mockRestore do to a spy?
- 3Can a spy call through to the original implementation?
- 4How do you configure automatic mock restoration?
Say it in the interview
jest.fn creates a fresh mock, so I use it when a dependency is injected and there is no real function to observe. jest.spyOn wraps an existing method, which is better when I want to verify it was called or temporarily change it. A spy can call through to the original unless I override it. I always restore spies or enable restoreMocks, otherwise the change leaks into later tests.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Jest mock interview and get scored feedback on depth, clarity and confidence.