I was doing some basic jest unit testing in attempt to learn it more.
I have this issue I do not know how to explain
This file has the child function add
// FileB.js
const add = (a, b) => {
return a b;
}
module.exports = {
add,
};
This file has the parent function addTen
// FileA.js
const { add } = require('./FileB');
const addTen = num => {
return add(10, num);
}
module.exports = {
addTen,
};
this is my test file, where I am trying to either check <mockedFunction/spy>.mock.calls
or do toHaveBeenCalledWith
to see if the inner child method, add, is being passed in 10,10 when i call addTen(10);
This file is not used in any real env, its simply me trying to learn jest unit testing more.
// randomTest.js
const { addTen } = require('../src/FileA');
const fileB = require('../src/FileB');
describe('temp', () => {
it('temp', () => {
const addSpy = jest.spyOn(fileB, 'add');
addTen(10);
console.log(addSpy.mock.calls);
expect(addSpy).toHaveBeenCalledWith(10,10)
});
});
Now for the issue, the test fails, saying add
was never called, or nothing passed in. I logged the add function within FileB
However, if I modify FileA
in this way, by importing entore module instead of destructuring, the test passes and I cna log out the functions and everything and see it works
This is what works
// FileA.js
const fileB = require('./FileB');
const addTen = num => {
return fileB.add(10, num);
}
module.exports = {
addTen,
};
Why does this slight change work?
CodePudding user response:
When you destructured add
from fileB
in FileA
, you created a new reference to the add function that is independent of the original add function in fileB
. When you mock fileB.add
, you are not mocking the add function that is being used in addTen.
On the other hand, when you do not destructure add from fileB
, the addTen function is using the original add function from fileB
, which is being mocked in your test. That's why the test passes when you import the entire fileB
module.
To make the test work with destructuring, you can mock the add function before you destructure it in FileA
, like this:
// FileA.js
jest.mock('./FileB', () => {
return {
add: jest.fn(() => 42),
};
});
const { add } = require('./FileB');
const addTen = num => {
return add(10, num);
}
module.exports = {
addTen,
};
Alternatively, you can keep the destructuring and mock add after it has been imported, but before you call addTen in your test:
// randomTest.js
const { addTen } = require('../src/FileA');
const { add } = require('../src/FileB');
jest.mock('../src/FileB', () => {
return {
add: jest.fn(() => 42),
};
});
describe('temp', () => {
it('temp', () => {
addTen(10);
expect(add).toHaveBeenCalledWith(10,10)
});
});