What’s the best way to correctly mock the following example?
The problem is that after import time, foo
keeps the reference to the original unmocked bar
.
module.js
:
JavaScript
x
8
1
export function bar () {
2
return 'bar';
3
}
4
5
export function foo () {
6
return `I am foo. bar is ${bar()}`;
7
}
8
module.test.js
:
JavaScript
1
36
36
1
import * as module from '../src/module';
2
3
describe('module', () => {
4
let barSpy;
5
6
beforeEach(() => {
7
barSpy = jest.spyOn(
8
module,
9
'bar'
10
).mockImplementation(jest.fn());
11
});
12
13
14
afterEach(() => {
15
barSpy.mockRestore();
16
});
17
18
it('foo', () => {
19
console.log(jest.isMockFunction(module.bar)); // outputs true
20
21
module.bar.mockReturnValue('fake bar');
22
23
console.log(module.bar()); // outputs 'fake bar';
24
25
expect(module.foo()).toEqual('I am foo. bar is fake bar');
26
/**
27
* does not work! we get the following:
28
*
29
* Expected value to equal:
30
* "I am foo. bar is fake bar"
31
* Received:
32
* "I am foo. bar is bar"
33
*/
34
});
35
});
36
I could change:
JavaScript
1
4
1
export function foo () {
2
return `I am foo. bar is ${bar()}`;
3
}
4
to:
JavaScript
1
4
1
export function foo () {
2
return `I am foo. bar is ${exports.bar()}`;
3
}
4
but this is pretty ugly in my opinion to do everywhere.
Advertisement
Answer
fwiw, the solution I settled on was to use dependency injection, by setting a default argument.
So I would change
JavaScript
1
8
1
export function bar () {
2
return 'bar';
3
}
4
5
export function foo () {
6
return `I am foo. bar is ${bar()}`;
7
}
8
to
JavaScript
1
8
1
export function bar () {
2
return 'bar';
3
}
4
5
export function foo (_bar = bar) {
6
return `I am foo. bar is ${_bar()}`;
7
}
8
This is not a breaking change to the API of my component, and I can easily override bar in my test by doing the following
JavaScript
1
9
1
import { foo, bar } from '../src/module';
2
3
describe('module', () => {
4
it('foo', () => {
5
const dummyBar = jest.fn().mockReturnValue('fake bar');
6
expect(foo(dummyBar)).toEqual('I am foo. bar is fake bar');
7
});
8
});
9
This has the benefit of leading to slightly nicer test code too 🙂