Reputation: 27852
I am mocking a library by doing this:
let helperFn;
let mock;
beforeEach(() => {
mock = jest.fn();
require('./helperFn').default = mock;
})
If I do this in a test, does it mean that from now on within the whole test suite that default function of helperFn will be associated with that mock?
In the Jest documentations I see how to reset the mock, but I don't see how to remove the mock from a required function. I am concerned that from that test on, all the calls into helperFn.default will see that mock.
Upvotes: 1
Views: 1681
Reputation: 45780
Here is an ES6 example:
helperFn.js
export default () => 'original';
code.js
import helperFn from './helperFn';
export const func = () => helperFn();
code.test.js
import * as helperFnModule from './helperFn';
import { func } from './code';
describe('helperFn mocked', () => {
let mock;
beforeEach(() => {
mock = jest.spyOn(helperFnModule, 'default');
mock.mockReturnValue('mocked');
});
afterEach(() => {
mock.mockRestore();
});
test('func', () => {
expect(func()).toBe('mocked'); // Success!
});
});
describe('helperFn not mocked', () => {
test('func', () => {
expect(func()).toBe('original'); // Success!
});
});
Details
Since ES6 imports are live views of the module exports, it is easy to mock an export and then restore it afterwards.
Here is a Node.js example:
helperFn.js
exports.default = () => 'original';
code.js
const helperFn = require('./helperFn').default;
exports.func = () => helperFn();
code.test.js
describe('helperFn mocked', () => {
beforeEach(() => {
const helperFnModule = require('./helperFn');
helperFnModule.default = jest.fn(() => 'mocked');
});
afterEach(() => {
jest.resetModules();
});
test('func', () => {
const { func } = require('./code');
expect(func()).toBe('mocked'); // Success!
});
});
describe('helperFn not mocked', () => {
test('func', () => {
const { func } = require('./code');
expect(func()).toBe('original'); // Success!
});
});
Details
The default
export gets remembered by code.js
when it runs, so changing the default
export of helperFn.js
doesn't affect func
once code.js
is required
. Jest
also caches modules and returns the same module for multiple require
calls unless jest.resetModules
is called.
So for Node.js modules it is often easiest to require
code within the test itself and use jest.resetModules
to reset any mocking.
Upvotes: 3