ECMAScript 模組
Jest 附帶實驗性 ECMAScript 模組 (ESM) 支援。
實作可能會有錯誤且缺乏功能。如需最新狀態,請查看 問題 和問題追蹤器上的 標籤。
另請注意,Jest 用於實作 ESM 支援的 API 仍 被 Node 視為實驗性(截至版本 18.8.0
)。
在提出警告後,以下是您在測試中啟用 ESM 支援的方式。
-
確保您已停用 程式碼轉換,方法是傳遞
transform: {}
或以其他方式設定轉換器以發出 ESM 而非預設的 CommonJS (CJS)。 -
使用
--experimental-vm-modules
執行node
,例如node --experimental-vm-modules node_modules/jest/bin/jest.js
或NODE_OPTIONS="$NODE_OPTIONS --experimental-vm-modules" npx jest
等。在 Windows 上,您可以使用
cross-env
來設定環境變數。如果您使用 Yarn,可以使用
yarn node --experimental-vm-modules $(yarn bin jest)
。如果您使用 Yarn Plug'n'Play,此命令也會運作。如果您的程式碼庫包含來自
*.wasm
檔案的 ESM 匯入,您不需要將--experimental-wasm-modules
傳遞給node
。Jest 中 WebAssembly 匯入的目前實作依賴於實驗性的 VM 模組,但這可能會在未來改變。 -
除此之外,我們嘗試遵循
node
啟用「ESM 模式」的邏輯(例如查看package.json
或.mjs
檔案中的type
),請參閱 他們的說明文件 以取得詳細資訊。 -
如果您想將其他副檔名(例如
.jsx
或.ts
)視為 ESM,請使用extensionsToTreatAsEsm
選項。
ESM 和 CommonJS 之間的差異
大多數的差異都說明在 Node 的說明文件 中,但除了那裡提到的內容之外,Jest 會將一個特殊變數注入到所有執行的檔案中 - jest
物件。若要存取 ESM 中的這個物件,您需要從 @jest/globals
模組匯入它或使用 import.meta
。
import {jest} from '@jest/globals';
jest.useFakeTimers();
// etc.
// alternatively
import.meta.jest.useFakeTimers();
// jest === import.meta.jest => true
ESM 中的模組模擬
由於 ESM 會在查看程式碼之前評估靜態 import
陳述式,因此 CJS 中發生的 jest.mock
呼叫提升在 ESM 中不會運作。若要在 ESM 中模擬模組,您需要在 jest.mock
呼叫後使用 require
或動態 import()
來載入模擬的模組 - 這也適用於載入模擬模組的模組。
ESM 模擬透過 jest.unstable_mockModule
支援。正如名稱所示,此 API 仍處於開發中,請追蹤 此議題 以取得更新。
jest.unstable_mockModule
的用法基本上與 jest.mock
相同,有兩個差異:工廠函式是必需的,而且它可以是同步或非同步的
import {jest} from '@jest/globals';
jest.unstable_mockModule('node:child_process', () => ({
execSync: jest.fn(),
// etc.
}));
const {execSync} = await import('node:child_process');
// etc.
對於模擬 CJS 模組,您應該繼續使用 jest.mock
。請參閱以下範例
const {BrowserWindow, app} = require('electron');
// etc.
module.exports = {example};
import {createRequire} from 'node:module';
import {jest} from '@jest/globals';
const require = createRequire(import.meta.url);
jest.mock('electron', () => ({
app: {
on: jest.fn(),
whenReady: jest.fn(() => Promise.resolve()),
},
BrowserWindow: jest.fn().mockImplementation(() => ({
// partial mocks.
})),
}));
const {BrowserWindow} = require('electron');
const exported = require('./main.cjs');
// alternatively
const {BrowserWindow} = (await import('electron')).default;
const exported = await import('./main.cjs');
// etc.