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.
Which Jest SpyOn error are you seeing?
Search the error text or choose the closest problem below.
Understand the error before changing the test
Each fix below shows the actual problem, the likely reason and the safest pattern to try next.
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().
You may be spying on the wrong object, using the wrong method name, or importing the module differently from how it is exported.
const user = {
getName() {
return 'Alex';
}
};
const spy = jest.spyOn(
user,
'getName'
);
user.getName();
expect(spy)
.toHaveBeenCalledTimes(1);
Confirm that the property exists on the same object reference your application actually calls.
Cannot redefine property
This usually happens when Jest attempts to replace a property that JavaScript does not allow to be reconfigured normally.
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.
import * as userModule
from './userService';
const spy = jest.spyOn(
userModule,
'getUser'
);
userModule.getUser();
expect(spy)
.toHaveBeenCalled();
Spy on a property Jest can actually replace, rather than assuming every imported binding is configurable.
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.
The spy must exist before the application makes the call you want Jest to record.
const spy = jest.spyOn(
service,
'send'
);
// Call application code after
// the spy has been created.
runFeature();
expect(spy)
.toHaveBeenCalledTimes(1);
Check whether your application uses the same object reference that the test is spying on.
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.
jest.spyOn() calls the original
implementation by default.
const spy = jest
.spyOn(api, 'send')
.mockImplementation(() => {
return undefined;
});
api.send();
expect(spy)
.toHaveBeenCalledTimes(1);
Use mockReturnValue(),
mockImplementation() or an async
mock helper when you do not want real behavior.
The target method is not a function
A normal two-argument jest.spyOn() call
expects the target property to be callable.
Getter and setter properties require a third
argument such as 'get' or
'set'.
const spy = jest.spyOn(
user,
'displayName',
'get'
);
const value = user.displayName;
expect(spy)
.toHaveBeenCalledTimes(1);
Determine whether you are dealing with a normal method, getter, setter or plain value before choosing the spy pattern.
A mocked spy affects another test
Tests can become unpredictable when a changed spy implementation remains active after the test that created it.
If you temporarily replace an implementation, clean it up before later tests depend on the real method again.
const spy = jest
.spyOn(service, 'getValue')
.mockReturnValue('mocked');
expect(service.getValue())
.toBe('mocked');
spy.mockRestore();
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.
Is the method really located on the object passed to
jest.spyOn()?
Was the spy created before your application made the call?
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.
Still working on your Jest test?
Choose the resource that matches what you need next.