Consider code -
// utils.js
export const foo = async (a, b) => {
// do something
bar(a)
}
export const bar = async (a) => {
// do something
}
// utils.spec.js
const utils = require('./utils');
const barSpy = jest.spyOn(utils, 'bar');
const result = await utils.foo('a', 'b');
expect(barSpy).toHaveBeenCalledTimes(1);
The test is failing -
Error: expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
I read /@DavideRama/mock-spy-exported-functions-within-a-single-module-in-jest-cdf2b61af642 and but could not solve this with multiple permutations.
Do you see any issue with this?
Consider code -
// utils.js
export const foo = async (a, b) => {
// do something
bar(a)
}
export const bar = async (a) => {
// do something
}
// utils.spec.js
const utils = require('./utils');
const barSpy = jest.spyOn(utils, 'bar');
const result = await utils.foo('a', 'b');
expect(barSpy).toHaveBeenCalledTimes(1);
The test is failing -
Error: expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
I read https://medium./@DavideRama/mock-spy-exported-functions-within-a-single-module-in-jest-cdf2b61af642 and https://github./facebook/jest/issues/936 but could not solve this with multiple permutations.
Do you see any issue with this?
Share Improve this question edited Sep 10, 2019 at 2:37 unknown_boundaries asked Sep 6, 2019 at 11:33 unknown_boundariesunknown_boundaries 1,6003 gold badges28 silver badges54 bronze badges 6- Hi, try by adding adding await while calling bar(a). export const foo = async (a, b) => { // do something await bar(a) } – Satya Pendem Commented Sep 6, 2019 at 12:28
- The call in debugger actually goes into the method. – unknown_boundaries Commented Sep 6, 2019 at 22:50
- no luck with await thing, it seems like more related to medium article shared. – unknown_boundaries Commented Sep 6, 2019 at 22:52
- The import way would not work - stackoverflow./questions/51269431/jest-mock-inner-function. This is in node.js – unknown_boundaries Commented Sep 10, 2019 at 2:37
- It is related to jest, but how export works. Did you try to move b to different file and export it? – Talgat Saribayev Commented Sep 10, 2019 at 12:16
2 Answers
Reset to default 3 +50As explained in the article that you shared, in your utils.js
file you are exporting an object that has foo
and bar
. Your utils.spec.js
actually imports exports.foo
and exports.bar
. Consequently, you mock exports.bar
By changing the utils.js
as below, when you mock bar you will be mocking the actual bar that foo uses.
utils.js
const bar = async () => {};
const foo = async () => {
exportFunctions.bar();
};
const exportFunctions = {
foo,
bar
};
module.exports = exportFunctions;
See this in action in this codesandbox. You can open a new terminal (bottom right) and run npm test
right in the browser
As @bhargav-shah said, when you spy on a module function with jest you are actually spying on its exported function values, not in the internal function itself.
This happens because of how monJS modules work. With an ES modules environment you could actually be able to achieve what you are trying to do here without modifying your code, as the exports would be bindings. A more in depth explanation can be found here.
At the moment Jest doesn't support ES modules, so the only way you could make your code work would be calling the actual exported function from your foo
function:
// utils.js
export const foo = async (a, b) => {
// do something
// Call the actual exported function
exports.bar(a)
}
export const bar = async (a) => {
// do something
}
// utils.spec.js
const utils = require('./utils');
const barSpy = jest.spyOn(utils, 'bar');
const result = await utils.foo('a', 'b');
expect(barSpy).toHaveBeenCalledTimes(1);