Mocking Default Export with ES6 Imports in Jest

I’ve encountered an issue with Jest mock default export. Specifically, when mocking the default export of a dependency in a tested module, the test suite fails with a TypeError: (0, _dependency.default) is not a function if the module imports the dependency using the ES6 import statement. However, the tests succeed when the module uses require().default instead.

I am puzzled because, as far as I understand, import module from location should directly translate to const module = require(location).default. I prefer to keep my code style consistent with the ES6 import syntax and avoid using require in the original module.

Is there a way to mock the default export correctly while using ES6 imports?

Here’s the test file with the mock:

import './modules.js';
import dependency from './dependency';

jest.mock('./dependency', () => {
  return {
    default: jest.fn()
  };
});

it('calls the mocked function', () => {
  expect(dependency).toHaveBeenCalled();
});

dependency.js:

export default () => console.log('do something');

module.js (not working):

import dependency from './dependency.js';
dependency();

module.js (working):

const dependency = require('./dependency.js').default;
dependency();

Is there a way to correctly mock the default export while using ES6 imports?

For ES modules, if you want to use import dependency from ‘./dependency’, you should mock it like this:

jest.mock('./dependency', () => ({
  ...jest.requireActual('./dependency'),
  __esModule: true,
  default: jest.fn(),
}));

This ensures Jest correctly interprets the module as an ES module and allows you to mock the default export properly.

Building on Ian’s suggestion, you can use either ES6 import or require to import your JavaScript files in Jest tests. Using ES6 import, Jest resolves all dependencies and calls the constructor for the imported class. During this step, you cannot mock the dependency; it must be resolved successfully before you can proceed with mocks.

Your issue is that your mock function assumes you are using require, but you are using ES6 import. For require, the mock setup looks like this:


jest.mock('./dependency', () => ({

default: jest.fn(),

}));

If you import your module using require, you would access it like this:


const test = require('./dependency');

test.default.doSomething();

When using ES6 import, adjust your mock setup to:


jest.mock('./dependency', () => jest.fn());

With ES6 import, you access the module like this:


import Test from './dependency';

Test();

This approach aligns with your preference for consistent ES6 import syntax while correctly setting up the jest mock default export.

Richaa’s advice is spot on, and I’d like to add another method that might simplify things further. Have you considered this approach? I struggled with mocking default exports for a while until I found this solution:


jest.mock('./dependency', () => () => jest.fn());

This approach works by treating the module as a function that returns a jest.fn(). This tells Jest to mock the entire ./dependency file as a function that returns a mock function.

By using this method, you can keep your ES6 import syntax consistent and ensure that the jest mock default export works correctly in your tests.