jest.mock() is invoked in the test case functional scope. Module imports are hoisted (internally moved to the beginning of the current scope). The original today function is imported before jest.mock() mocks the utils/date module.
You can move the jest.mock() from test case functional scope to module scope. Jest will automatically hoist jest.mock calls to the top of the module (before any imports). So that when you import the today function, it is already being mocked.
See Using with ES module imports:
If you're using ES module imports then you'll normally be inclined to put your
importstatements at the top of the test file. But often you need to instruct Jest to use a mock before modules use it. For this reason, Jest will automatically hoistjest.mockcalls to the top of the module (before any imports).
import { today } from 'utils/date';
jest.mock('utils/date', () => ({
today: jest.fn(() => '01-01-2020'),
}));
it('should work properly', () => {
expect(jest.isMockFunction(today)).toBeTruthy();
expect(today()).toBe('01-01-2020');
});
Answer from Lin Du on Stack OverflowTesting Imported Function with Parameter using Jest Mock Function / Jest spyOn
How can I mock an ES6 module import using Jest?
Anyone have an article/video around that's a deep dive on Jest imports and mocking?
I hate mocking Typescript classes with Jest
Edit: Several years have passed and this isn't really the right way to do this any more (and probably never was, my bad).
Mutating an imported module is nasty and can lead to side effects like tests that pass or fail depending on execution order.
I'm leaving this answer in its original form for historical purposes, but you should really use jest.spyOn or jest.mock. Refer to the jest docs or the other answers on this page for details.
Original answer follows:
I've been able to solve this by using a hack involving import *. It even works for both named and default exports!
For a named export:
// dependency.js
export const doSomething = (y) => console.log(y)
// myModule.js
import { doSomething } from './dependency';
export default (x) => {
doSomething(x * 2);
}
// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';
describe('myModule', () => {
it('calls the dependency with double the input', () => {
dependency.doSomething = jest.fn(); // Mutate the named export
myModule(2);
expect(dependency.doSomething).toBeCalledWith(4);
});
});
Or for a default export:
// dependency.js
export default (y) => console.log(y)
// myModule.js
import dependency from './dependency'; // Note lack of curlies
export default (x) => {
dependency(x * 2);
}
// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';
describe('myModule', () => {
it('calls the dependency with double the input', () => {
dependency.default = jest.fn(); // Mutate the default export
myModule(2);
expect(dependency.default).toBeCalledWith(4); // Assert against the default
});
});
You have to mock the module and set the spy by yourself:
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
doSomething: jest.fn()
}))
describe('myModule', () => {
it('calls the dependency with double the input', () => {
myModule(2);
expect(dependency.doSomething).toBeCalledWith(4);
});
});