Jest Mocks with ES Modules

Jest’s support for mocks with CommonJS modules works great, they’re easy to use and it works great, as per the docs.

With ES Modules on the other hand, the docs are vague, and after spending several hours trying to get them to work with code I needed to test and not having any success, I spent a few more hours getting it to work with even the simplest example code.

This current issue describes multiple approaches which others have had varying success with, but there’s one tip mentioned that I can confirm is key to getting the mocks to work with ES modules and this is currently not mentioned in the docs (at least when I last looked) – you must await the import for the module you are mocking. This needs to be combined with the following:

  1. jest.unstable_mockModule() need to be called at the top level, and must be before the import for the module you are mocking
  2. You must await the import

To explain the last point, you must use this:

const { example2WithModule } = await import(‘./example.js’);

and not this:

import { example2WithModule } from ‘./example.js’;

Here’s an example of my working usage of jest.unstable_mockModule():

jest.unstable_mockModule('./example-module.js', () => ({
    exampleFunctionFromModule: jest.fn(
        () => {
            return 'mocked return!';
        }
    )
}));

node16 and Jest with ES6+ modules

I’ve run into this a few times, so leaving some notes for myself for next time,

By default, attempting to use “import x from ‘y’ ” style ES6 module imports with Jest will give you this error:

SyntaxError: Cannot use import statement outside a module

With node16, support for modules is added with the experiemental-vm option, so update your package.json to add a script executing jest with this flag:

"test": "node --experimental-vm-modules node_modules/.bin/jest"

and then also in your package.json, add:

  "type": "module",

If you search for the ‘cannot use import statement outside a module error there are plenty of recommendations, including more elaborate babel transpile ES6 modules to CommonJS style requires.

Depending what you’re doing maybe you’ll need some of the other approaches too, but I found the above 2 steps to be the bare minimum