Reputation: 12133
When using jest
with ES6 modules and babel-jest
, all the jest.mock
calls are hoisted.
Let's say I'd like to mock fs
module for the tested class, but preserve the original implementation for the rest of the modules (for example some utils that I use during the test).
Consider the following example:
class UnderTest {
someFunction(){
fs.existsSync('blah');
}
}
class TestUtility {
someOtherFunction(){
fs.existsSync('blahblah');
}
}
the test:
it('Should test someFunction with mocked fs while using TestUtility'', () => {
testUtility.someOtherFunction(); // Should work as expected
underTest.someFunction(); // Should work with mock implementation of 'fs'
})
Now, one would expect that with the following approach the fs
module will be mocked for UnderTest
but not for TestUtility
.
import {TestUtility} from './test-utility';
jest.mock('fs');
import {UnderTest } from './under-test';
However, due to the hoisting, fs
module will be mocked for all the modules (which is undesirable).
Is there any way to achieve the described behavior?
Upvotes: 2
Views: 2021
Reputation: 6771
To opt out from mocking a module in a test jest.doMock(moduleName, factory, options)
and jest.dontMock(moduleName)
should be used.
jest.doMock(moduleName, factory, options)
When using
babel-jest
, calls tomock
will automatically be hoisted to the top of the code block. Use this method if you want to explicitly avoid this behavior.
jest.dontMock(moduleName)
When using
babel-jest
, calls tounmock
will automatically be hoisted to the top of the code block. Use this method if you want to explicitly avoid this behavior.
So in your case I would try something like
beforeEach(() => {
jest.resetModules();
});
it('Should test someFunction with mocked fs while using TestUtility'', () => {
jest.dontMock('fs');
testUtility.someOtherFunction(); // Should work as expected
jest.doMock('fs', () => {
return ... // return your fs mock implementation;
});
underTest.someFunction(); // Should work with mock implementation of 'fs'
})
Upvotes: 2
Reputation: 1032
You should probably use jest's requireActual
:
const fs = jest.requireActual('fs'); // Unmockable version of jest
class TestUtility {
someOtherFunction(){
fs.existsSync('blahblah');
}
}
From the documentation:
Jest allows you to mock out whole modules in your tests, which can be useful for testing your code is calling functions from that module correctly. However, sometimes you may want to use parts of a mocked module in your test file, in which case you want to access the original implementation, rather than a mocked version.
Upvotes: 0