Expected result:
Jest Error Finder Ready
Understand Jest SpyOn. Fix errors faster.
Learn how jest.spyOn() works or paste your
error to find its cause and the safest fix.
Read-only export cannot be replaced
This export is protected by the module. Mock the module and replace only the function you need.
Keeps the real module and replaces only the protected export.
jest.mock('./router', () => ({
...jest.requireActual('./router'),
useNavigate: jest.fn(),
}));
Jest SpyOn explained
What is jest.spyOn()?
jest.spyOn() watches an existing method during
a test. It records each call and its arguments while keeping
the real method available.
Important: a spy calls the original method by default. Mock it only when that behaviour should be replaced.
const userService = {
getName: () => 'Ali',
};
const spy = jest.spyOn(userService, 'getName');
userService.getName();
expect(spy).toHaveBeenCalledTimes(1);
Test passed getName was called once.
6 ms
Interactive Jest playground
One test. Three Jest patterns.
Compare three practical approaches and choose the right Jest pattern before writing your test.
jest.spyOn()
Pattern 1 of 3: Watch an existing method with jest.spyOn().
Copy-ready Jest recipes
Use jest.spyOn() in real tests.
Choose a testing goal, understand the pattern, and copy a working example.
COMMON SPY PROBLEMS
Fix common jest.spyOn() errors.
Choose the error you see and get the cause, corrected code, and safest fix.
Cannot redefine property
Why it happens
JEST SPYON GUIDE
Jest SpyOn Explained:
How jest.spyOn() Works in Real Tests
Understand what Jest SpyOn watches, what it records, when the original function runs, and how to safely control a spy in your tests.
Jest SpyOn is one of the most useful Jest
features when you need to understand how an existing method
behaves during a test. Instead of creating a completely new
function, jest.spyOn() watches a method that
already exists and records how your application uses it.
This makes a Jest spy useful when testing services, utilities, API helpers, event handlers, logging functions, and other methods that your application already calls.
How Does Jest SpyOn Work?
A Jest spy is attached to a method on an object. Once the spy exists, Jest can track calls to that method while your test continues to use it normally.
For example, imagine a service with a method that saves a user. You can spy on that method and then check whether your application called it correctly.
const userService = {
saveUser(name) {
return `Saved ${name}`;
}
};
const spy = jest.spyOn(userService, 'saveUser');
userService.saveUser('Alex');
expect(spy).toHaveBeenCalled();
What Does jest.spyOn() Record?
After the method is called, Jest stores useful information about that call. You can check whether the method ran, how many times it was called, and which arguments it received.
toHaveBeenCalled()
Checks whether the method was called.
toHaveBeenCalledTimes(1)
Checks the exact number of calls.
toHaveBeenCalledWith('Alex')
Checks the arguments passed to it.
Jest also stores call results inside the spy's mock data. This information can be especially helpful when a test fails even though the expected method appears to be running.
Does Jest SpyOn Call the Original Function?
Yes. By default, jest.spyOn() allows the
original implementation to run. Creating a spy does not
automatically replace the method with an empty mock.
Watching a method and replacing its behavior are two different things.
This matters when the original method sends an API request, writes data, sends an email, or performs another side effect.
How Do You Replace a Jest Spy's Behavior?
When you want to observe a method without allowing its real implementation to run, combine Jest SpyOn with a mock helper.
const spy = jest
.spyOn(api, 'sendRequest')
.mockImplementation(() => undefined);
If you only need to control the returned value, you can use
mockReturnValue(). Async methods can also use
helpers such as mockResolvedValue() or
mockRejectedValue() when appropriate.
Jest SpyOn vs jest.fn()
Both tools create mock-function behavior, but they are
normally used for different jobs. Use
jest.spyOn() when the real method already
exists and you want to watch or temporarily control it.
Use jest.fn() when you need a new fake function
rather than a spy around an existing object method.
jest.spyOn() watches an existing method.
jest.fn() creates a mock function.
Why Should You Restore a Jest Spy?
A spy temporarily changes the method it watches. If it stays active after a test finishes, it can affect another test and make failures difficult to understand.
spy.mockRestore();
// Or restore spies after every test
afterEach(() => {
jest.restoreAllMocks();
});
Restoring your spies helps keep tests isolated and makes your Jest test suite more predictable.
Think of Jest SpyOn as a temporary watcher.
Jest SpyOn watches an existing method, records how it was called, and lets you control its behavior when necessary. Remember that the real implementation runs by default, use mock helpers only when you need them, and restore your spy after the test.
COMMON QUESTIONS
Jest SpyOn FAQs
Quick answers to the questions developers ask most when working
with jest.spyOn().
Yes. By default, jest.spyOn() still calls
the original implementation. If you need to stop or
change that behavior, use
mockImplementation(),
mockReturnValue(), or another suitable Jest
mock helper.