Reputation: 639
Apparently mock.mockRestore() does not restore the original implementation of a mock created using jest.mock()
// a.js
export default class A {}
// b.js
import A from './a';
export default class B extends A {}
// test.js
import A from './a';
import B from './b';
jest.mock('./a');
jest.mock('./b');
const b = new B();
test('instanceOf', () => {
A.mockRestore();
B.mockRestore();
expect(b).toBeInstanceOf(A); // fails
});
Upvotes: 38
Views: 38299
Reputation: 2822
Assuming you cant use spyOn, you can do something like this:
// test.js
jest.mock('./a');
import A from './a';
A.mockImplementation(params => 'mockVal');
const actualA = jest.requireActual('./a');
test('instanceOf', () => {
A.mockRestore(); // acts like mockReset()
A.mockImplementation((params) => {
return actualA(params);
});
});
Upvotes: 1
Reputation: 45780
mockFn.mockRestore
only works for a mock function created with jest.spyOn
:
const obj = {
func: () => 'original'
}
test('func', () => {
const mock = jest.spyOn(obj, 'func');
mock.mockReturnValue('mocked');
expect(obj.func()).toBe('mocked'); // Success!
mock.mockRestore();
expect(obj.func()).toBe('original'); // Success!
})
jest.spyOn
wraps the original function and provides mockRestore
as a way to restore the original function.
jest.mock
calls work a little differently.
Jest
takes over the require
system and jest.mock
tells Jest
that it should return the module mock instead of the actual module whenever it is required.
This means that the module mock doesn't wrap the original module, it completely replaces the original module in the require
system. So mockRestore
may be defined on mock functions within the module mock, but calling it doesn't restore the original implementation.
jest.mock
is typically used when you want to mock an entire module for the whole test.
It is particularly useful when using ES6-style import
statements since babel-jest
hoists jest.mock
calls and they run before anything else in the test file (including any import
statements):
import A from './a'; // <= A is already mocked...
jest.mock('./a'); // <= ...because this runs first
test('A', () => {
// ...
}
There isn't an easy way to restore the original module during a test that uses jest.mock
since its primary use is to mock a module for an entire test.
If you are trying to use both a mock and the original implementation during the same test there are a few options:
jest.spyOn
and restore it using mockRestore
jest.doMock
to avoid the hoisting behavior of jest.mock
...just note you also need to use require
within the scope that uses jest.doMock
instead of using a top-level import
jest.requireActual
at any time to require
the original moduleUpvotes: 56