JeB
JeB

Reputation: 12133

Jest mock module for single import

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

Answers (2)

brass monkey
brass monkey

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 to mock 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 to unmock 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

Karamell
Karamell

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

Related Questions