Jest SpyOn examples for real tests
Find the testing goal you need, understand why the
pattern works, and copy a clean
jest.spyOn() example without digging
through unrelated documentation.
const spy = jest
.spyOn(api, 'getUser')
.mockResolvedValue({
id: 1,
name: 'Alex'
});
await api.getUser();
expect(spy)
.toHaveBeenCalledTimes(1);
What are you trying to test?
Choose your testing goal and jump directly to the smallest useful Jest SpyOn example.
Copy the pattern that matches your test
Each example starts with the testing intent, shows the minimum useful code and explains what the assertion proves.
Basic jest.spyOn() example
Start here when the real method already exists and you only need to check whether your application called it.
You want to watch an existing method without changing what that method does.
const user = {
getName() {
return 'Alex';
}
};
const spy = jest.spyOn(user, 'getName');
user.getName();
expect(spy).toHaveBeenCalledTimes(1);
Jest confirms that
user.getName() was called once.
The original function still runs.
Check arguments with toHaveBeenCalledWith()
Use this pattern when the important question is not only whether the function ran, but exactly what data your application passed to it.
You need to verify a string, object, ID, options object or another value passed into a method.
const api = {
send(message) {
return message;
}
};
const spy = jest.spyOn(api, 'send');
api.send('hello');
expect(spy)
.toHaveBeenCalledWith('hello');
The method was called with exactly
'hello'.
Mock a return value
Use mockReturnValue() when the method is
synchronous and your test needs a predictable result
instead of the real value.
The real implementation is unpredictable, expensive or irrelevant to the behavior you are currently testing.
const userService = {
getName() {
return 'Real User';
}
};
const spy = jest
.spyOn(userService, 'getName')
.mockReturnValue('Test User');
expect(userService.getName())
.toBe('Test User');
expect(spy)
.toHaveBeenCalledTimes(1);
mockReturnValue(), the real
implementation does not run for that mocked call.
Replace behavior with mockImplementation()
Use mockImplementation() when one fixed
return value is not enough and the mock needs its own
logic.
Your fake method needs to inspect parameters, calculate a value or behave differently for different inputs.
const math = {
multiply(a, b) {
return a * b;
}
};
const spy = jest
.spyOn(math, 'multiply')
.mockImplementation((a, b) => {
return a + b;
});
expect(math.multiply(4, 5))
.toBe(9);
expect(spy)
.toHaveBeenCalledWith(4, 5);
The spy still records every call while your test controls exactly what the method does.
Mock async success with mockResolvedValue()
Use this pattern when the real method returns a Promise and your test needs a successful response without making a real request.
You are testing API, database or other Promise-based application behavior.
const api = {
async getUser() {
return fetch('/user');
}
};
const spy = jest
.spyOn(api, 'getUser')
.mockResolvedValue({
id: 1,
name: 'Alex'
});
await expect(api.getUser())
.resolves
.toEqual({
id: 1,
name: 'Alex'
});
expect(spy)
.toHaveBeenCalledTimes(1);
Your unit test does not need a real network request to receive a predictable result.
Mock async failure with mockRejectedValue()
Use this when you need to verify what your application does after an API request, database call or another Promise rejects.
You need to test error handling, retries, fallback messages or failed requests.
const spy = jest
.spyOn(api, 'getUser')
.mockRejectedValue(
new Error('Request failed')
);
await expect(api.getUser())
.rejects
.toThrow('Request failed');
expect(spy)
.toHaveBeenCalledTimes(1);
Spy on a class method
Instance methods usually live on the class prototype. Spy on the prototype before your application creates or uses the instance.
Your method belongs to instances created from a class rather than a plain object.
class UserService {
getName() {
return 'Alex';
}
}
const spy = jest.spyOn(
UserService.prototype,
'getName'
);
const service = new UserService();
service.getName();
expect(spy)
.toHaveBeenCalledTimes(1);
The method lives on
UserService.prototype, so that
is the object Jest needs to watch.
Spy on a getter
Getter and setter properties are not ordinary callable methods. Pass a third argument to tell Jest which accessor you want to spy on.
The property is accessed with a getter or setter rather than called like a function.
const user = {
firstName: 'Alex',
get displayName() {
return this.firstName;
}
};
const spy = jest.spyOn(
user,
'displayName',
'get'
);
const name = user.displayName;
expect(name).toBe('Alex');
expect(spy)
.toHaveBeenCalledTimes(1);
'set' instead of
'get' as the third argument.
Restore the original method with mockRestore()
Restore a spy after changing its implementation so mocked behavior does not leak into another test.
You temporarily replaced the real method and need the original implementation again.
const service = {
getValue() {
return 'real';
}
};
const spy = jest
.spyOn(service, 'getValue')
.mockReturnValue('mocked');
expect(service.getValue())
.toBe('mocked');
spy.mockRestore();
expect(service.getValue())
.toBe('real');
Jest removes the temporary spy behavior and restores the original method.
Common questions about Jest SpyOn examples
Quick answers for choosing the right spy pattern for your test.
Create the spy using
jest.spyOn(object, 'method'), call the
method and assert the call with a matcher such as
toHaveBeenCalledTimes().
Chain mockReturnValue() after
jest.spyOn() for synchronous values.
For successful Promises, use
mockResolvedValue().
For a normal instance method, spy on
ClassName.prototype. Static methods
should be spied on directly from the class.
Restore the spy when you changed its implementation and want to make sure temporary mocked behavior does not affect another test.
Need more than an example?
Continue with the Jest resource that matches what you need next.