Skip to main content
JestSpyOn

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.

Try an example:
Works in your browser No signup required Copyable code fixes

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.

user-service.test.js Live example
Working test
const userService = {
  getName: () => 'Ali',
};

const spy = jest.spyOn(userService, 'getName');
userService.getName();

expect(spy).toHaveBeenCalledTimes(1);

Test passed getName was called once.

6 ms

One test. Three Jest patterns.

Compare three practical approaches and choose the right Jest pattern before writing your test.

Active pattern jest.spyOn()
Jest spyOn, fn and mock examples displayed on a laptop and mobile phone
Watch a real method without replacing its implementation.

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.

user-service.test.js Call tracking

Expected result:

COMMON SPY PROBLEMS

Fix common jest.spyOn() errors.

Choose the error you see and get the cause, corrected code, and safest fix.

MODULE EXPORT Safest fix

Cannot redefine property

Why it happens

Broken
example.test.js
Fixed
Why the fix works

Prevent it next time

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.

01

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.

Basic example
const userService = {
  saveUser(name) {
    return `Saved ${name}`;
  }
};

const spy = jest.spyOn(userService, 'saveUser');

userService.saveUser('Alex');

expect(spy).toHaveBeenCalled();
02

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.

03

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.

Remember this

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.

04

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.

Replace the implementation
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.

05

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.

Simple rule jest.spyOn() watches an existing method. jest.fn() creates a mock function.
06

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.

Restore the method
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.

FINAL TAKEAWAY

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.