Jest SpyOn troubleshooting

Fix common Jest SpyOn errors faster

Find the error you are seeing, understand why jest.spyOn() failed, and use the smallest practical fix without guessing your way through the test.

user.test.js Failed
Property `getName` does not exist in the provided object
jest.spyOn(user, 'getName');
Check the object that actually owns the method before creating the spy.

Understand the error before changing the test

Each fix below shows the actual problem, the likely reason and the safest pattern to try next.

Error 01

Property does not exist on the provided object

Jest cannot create a spy if the method is not present on the exact object you passed to jest.spyOn().

Typical error Property `getName` does not exist in the provided object
Why this happens

You may be spying on the wrong object, using the wrong method name, or importing the module differently from how it is exported.

Correct target
const user = {
  getName() {
    return 'Alex';
  }
};

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

user.getName();

expect(spy)
  .toHaveBeenCalledTimes(1);
Check first

Confirm that the property exists on the same object reference your application actually calls.

Error 02

Cannot redefine property

This usually happens when Jest attempts to replace a property that JavaScript does not allow to be reconfigured normally.

Typical error TypeError: Cannot redefine property
Why this happens

The export or property may be non-configurable, or you may be attempting to spy on an imported binding instead of an object property Jest can replace.

Spy on the module object
import * as userModule
  from './userService';

const spy = jest.spyOn(
  userModule,
  'getUser'
);

userModule.getUser();

expect(spy)
  .toHaveBeenCalled();
Main idea

Spy on a property Jest can actually replace, rather than assuming every imported binding is configurable.

Error 03

Spy records zero calls

Your test may fail even though the function appears to run if the spy was created after the call or attached to a different reference.

Typical assertion failure Expected number of calls: 1 Received number of calls: 0
Timing matters

The spy must exist before the application makes the call you want Jest to record.

Create the spy first
const spy = jest.spyOn(
  service,
  'send'
);

// Call application code after
// the spy has been created.
runFeature();

expect(spy)
  .toHaveBeenCalledTimes(1);
If it still shows zero

Check whether your application uses the same object reference that the test is spying on.

Error 04

The real method still runs

This is one of the most common sources of confusion: creating a spy does not automatically turn the method into an empty fake.

This is expected behavior

jest.spyOn() calls the original implementation by default.

Stop the real implementation
const spy = jest
  .spyOn(api, 'send')
  .mockImplementation(() => {
    return undefined;
  });

api.send();

expect(spy)
  .toHaveBeenCalledTimes(1);
Choose the right mock

Use mockReturnValue(), mockImplementation() or an async mock helper when you do not want real behavior.

Error 05

The target method is not a function

A normal two-argument jest.spyOn() call expects the target property to be callable.

Typical problem Cannot spy on the property because it is not a function
It may be a getter

Getter and setter properties require a third argument such as 'get' or 'set'.

Spy on a getter
const spy = jest.spyOn(
  user,
  'displayName',
  'get'
);

const value = user.displayName;

expect(spy)
  .toHaveBeenCalledTimes(1);
Inspect the property first

Determine whether you are dealing with a normal method, getter, setter or plain value before choosing the spy pattern.

Error 06

A mocked spy affects another test

Tests can become unpredictable when a changed spy implementation remains active after the test that created it.

Restore your spies

If you temporarily replace an implementation, clean it up before later tests depend on the real method again.

Restore after the test
const spy = jest
  .spyOn(service, 'getValue')
  .mockReturnValue('mocked');

expect(service.getValue())
  .toBe('mocked');

spy.mockRestore();
Result

The original implementation becomes available again instead of leaking the mock into another test.

Three things to check when a spy fails

Most Jest SpyOn failures become easier to understand once you verify these three details.

1. Check the target

Is the method really located on the object passed to jest.spyOn()?

2. Check the timing

Was the spy created before your application made the call?

3. Check the behavior

Do you want the real method to run, or should the spy replace its implementation?

Jest SpyOn troubleshooting questions

Quick answers to problems that commonly appear while debugging spies.

The method is usually missing from the object you passed to Jest, the method name is incorrect, or the module was imported in a different shape.

Create the spy before the application call and verify that your application uses the same object reference that your test is spying on.

That is the default behavior of jest.spyOn(). Add a mock implementation or mock return value when the real method should not execute.

Restore the spy after the test when you have replaced the implementation, or use an appropriate shared test cleanup strategy.