When writing Jest unit tests, I always struggle to remember the syntax for mocking modules. So this post is intended as a part-guide, part-cheatsheet to refresh your memory when you need to do some mocking.
Mocking a named import
If you wanted to mock a imported named function, say getTime
:
// Usage
import { getTime } from './time';
// test.js
jest.mock('./time', () => ({
getTime: () => '1:11PM',
}));
Mocking only the named import (and leaving other imports unmocked)
If there are multiple functions in a module, and you only want to mock one, you can use requireActual
:
// Usage
import { getTime, isMorning } from './time';
// test.js
jest.mock('./time', () => ({
...jest.requireActual('./time'),
getTime: () => '1:11PM',
// isMorning will return its true value
}));
Mocking a default import
// Usage
import getDayOfWeek from './time';
// test.js
jest.mock('./time', () => () => 'Monday');
Mocking default and named imports
If you want to mock default and named imports, youβll need to remember to use __esModule: true
:
// Usage
import getDayOfWeek, { getTime } from './time';
// test.js
jest.mock('./time', () => ({
__esModule: true,
default: () => 'Thursday'
getTime: () => '1:11PM',
}));
Changing what the mock returns per test
Using mockReturnValue
If you wanted to have getDayOfWeek
to return a different value per test, you can use mockReturnValue
in each of your tests:
import getDayOfWeek from './time';
jest.mock('./time', () => jest.fn());
test('App renders Monday', () => {
getDayOfWeek.mockReturnValue('Monday');
//...
});
test('App renders Tuesday', () => {
getDayOfWeek.mockReturnValue('Tuesday');
//...
});
If you only wanted to change what the mocked function returned for just one test, beware you donβt do something like this, as it wonβt work:
jest.mock('./time', () => jest.fn(() => 'Tuesday'));
test('App renders Tuesday', () => {
// Passes
});
test('App renders Monday', () => {
getDayOfWeek.mockReturnValue('Monday');
// Passes
});
test('App renders Tuesday, again', () => {
// Fails
});
This is because calling mockReturnValue
inside a test still changes the mock for all other tests after it.
Using mockReturnValueOnce
To get around the above scenario, you could use mockReturnValueOnce
:
jest.mock('./time', () => jest.fn(() => 'Tuesday'));
test('App renders Monday', () => {
getDayOfWeek.mockReturnValueOnce('Monday');
// Passes
});
test('App renders Tuesday', () => {
// Passes
});
mockReturnValueOnce
will return a Monday
once, and then resume returning Tuesday
for all other tests.
Defining the mocks in beforeEach
Alternatively you can define the mock before each test, and then call mockReturnValue
inside the Monday test to override the mock just for that test:
jest.mock('./time', () => jest.fn());
beforeEach(() => {
getDayOfWeek.mockReturnValue('Tuesday');
});
test('App renders Tuesday', () => {
// Passes
});
test('App renders Monday', () => {
getDayOfWeek.mockReturnValue('Monday');
// Passes
});
test('App renders Tuesday, again', () => {
// Passes
});
Personally Iβd prefer this approach over using mockReturnValueOnce
as I think itβs less likely to cause confusion or end up in a scenario where your mocks are in a weird state.
Clearing mocks between tests with clearAllMocks
If we declare the mock once, its call count doesnβt reset between tests. So the second test here would fail:
jest.mock('./time', () => jest.fn(() => 'Tuesday'));
test('Calls getDayOfWeek function once', () => {
render(<App />);
expect(getDayOfWeek).toBeCalledTimes(1);
});
test('Calls getDayOfWeek function once, again', () => {
render(<App />);
expect(getDayOfWeek).toBeCalledTimes(1); // getDayOfWeek has been called twice
});
We would need to make sure we clear the call count between each test by calling clearAllMocks
:
beforeEach(() => {
jest.clearAllMocks();
});
test('Calls getDayOfWeek function once', () => {
// ...
Chaining mocks
As one final tip, when mocking multiple modules you can chain them like so:
jest
.mock('./time', () => jest.fn())
.mock('./space', () => jest.fn());
Top comments (4)
this has been by far the most helpful guide to module mocking I have ever come across, thanks for writing!
You're welcome!
Thanks for this article. Found it while looking how to mock functions with named imports and your article (on your own blog) really made it all clear to me.
Awesome! Glad I could help