This example is explained in Jest Docs's Manual Mocks section, and the source files are downloaded from Jest examples/manual-mocks.
As mentioned in the ECMAScript Modules, jest's ECMAScript Modules (ESM) support is experimental.
This example is to find the workaround for Jest ES Module support without Babel, and is related to the following issues:
file to import (require) | file to be imported (required) | Static Import | Dynamic Import | require |
---|---|---|---|---|
ESM | ESM | OK | OK | NG |
CJS | CJS | NG | NG | OK |
ESM | CJS | OK | NG | NG 1 |
CJS | ESM | NG | OK | NG |
ESM (ES Modules), CJS (CommonJS), NG (No Good)
The above table is from the Blog post TypeScript 4.7 と Native Node.js ESM.
$ git clone <this repository>
$ npm install
# jest --verbose
$ npm run dev:test
# or jest --silent
$ npm test
OS: Windows11
Node: v16.15.1
Jest: v28.1.2
test file (tests/) | file to be imported (required) | Mock | PASS/FAIL |
---|---|---|---|
file_summarizer.test.js | FileSummarizer.cjs | node/fs CommonJS Mock (ESM require CommonJS) | PASS 2 |
FileSummarizer.test.js | FileSummarizer.js | No Mock (ESM import node/fs module) | PASS |
FileSummarizerCJS.test.js | FileSummarizer.cjs | No Mock (ESM require CommonJS) | PASS |
FileSummarizerESM.test.js | FileSummarizer.mjs | No Mock (ESM import ESM) | FAIL 3 |
user.test.js | models/user.mjs | No Mock (ESM import ESM) | PASS |
userMocked.test.js | models/user.mjs | ESM Mock (ESM import ESM) | FAIL 4 |
Babel based Jest examples/manual-mocks example is executable without Babel, after "FileSummarizer.js" is renamed to "FileSummarizer.cjs" and the following modification of "file_summarize.test.js":
// 'use strict';
import { jest } from '@jest/globals';
// Node.js - `module.createRequire(filename)`
// https://nodejs.org/api/module.html#modulecreaterequirefilename
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
jest.mock('fs');
FAIL __tests__/file_summarizerESM.test.js
listFilesInDirectorySync
× includes all files in the directory in the summary (1 ms)
● listFilesInDirectorySync › includes all files in the directory in the summary
TypeError: fs.setMockFiles is not a function
16 | // Set up some mocked out file info before each test
17 | const fs = await import('node:fs');
> 18 | fs.setMockFiles(MOCK_FILE_INFO);
| ^
import('../models/user.mjs')
dose not import from 'models/mocks/user.mjs', but import 'models/user.mjs'.
FAIL __tests__/userMocked.test.js
× if user model is mocked (8 ms)
● if user model is mocked
expect(received).toEqual(expected) // deep equality
- Expected - 2
+ Received + 2
Object {
- "age": 622,
- "name": "Mock name",
+ "age": 26,
+ "name": "Real name",
}
20 | const user = await import('../models/user.mjs');
21 | const expected = { age: 622, name: 'Mock name' };
> 22 | expect(user.default.getAuthenticated()).toEqual(expected);
| ^
syncBuiltinESMExports.cjs is from Node.js - Modules: node:module API - module.syncBuiltinESMExports()
To execute node syncBuiltinESMExports.cjs
outputs nothing.
Facebook has the Copyright of the source code.
Footnotes
-
The table marks "NG", but
module.createRequire(filename)
enable ESM to require CJS. ↩ -
explained below "Workaround" section ↩
-
explained below "Issue 1" section ↩
-
explained below "Issue 2" section ↩