Testing ECMAScript Modules Natively in Jest
on nodejs and javascript
In this tutorial, we’ll setup Jest to test a Node.js application that uses ECMAScript modules (ESM). Recent versions of Node.js have full support for ESM, which will eventually become the default mode in place of CommonJS. In the meantime, ESM mode can be easily enabled by setting "type": "module"
in package.json
.
Typically, Jest relies on Babel to transpile ESM code to CommonJS before running any tests, but Babel just adds another layer of complexity. Jest already has built-in support for ESM, though currently at an experimental stage.
There are a few key differences from testing CommonJS modules:
- We need to pass the
--experimental-vm-modules
flag to node when running Jest - Instead of
jest.mock
we have to usejest.unstable_mockModule
- The
jest
object has to be imported from@jest/globals
- We have to use dynamic imports to load our mocked modules in the right place
Let’s assume we export the following class in myClass.js
.
export class MyClass {
async get() {
return Promise.resolve("Hello World!");
}
}
In myClass.test.js
we could create a mock of our MyClass
class like so:
import { jest } from "@jest/globals";
const mockedGet = jest.fn().mockResolvedValue("Mocked");
jest.unstable_mockModule("./myClass.js", () => {
return {
MyClass: jest.fn(() => ({
get: mockedGet,
})),
};
});
// ESM import statements are evaluated first, so we need
// to use a dynamic import() to make sure our mocked module
// is loaded after jest.unstable_mockModule()
const { MyClass } = await import("./myClass.js");
const myInstance = new MyClass();
describe("MyClass", () => {
beforeEach(() => {
mockedGet.mockClear();
});
it("should work", async () => {
const result = await myInstance.get();
expect(result).toEqual("Mocked");
});
});
Finally, we should pass the --experimental-vm-modules
flag to node, which can be added to our package.json
.
...
"type": "module",
"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
}
...
For more information on using Jest with ECMAScript modules, you can have a look at the official docs.