Zum Hauptinhalt springen
Version: Nächste

ECMAScript-Module

Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

Vorsicht

Jest bietet experimentelle Unterstützung für ECMAScript-Module (ESM).

Die Implementierung kann Fehler enthalten und Funktionen vermissen. Für den aktuellen Status siehe das Issue und das Label im Issue-Tracker.

Beachten Sie auch, dass die APIs, die Jest für die ESM-Unterstützung verwendet, von Node weiterhin als experimentell betrachtet werden (Stand Version 18.8.0).

Nach diesen Warnungen zeigen wir Ihnen, wie Sie die ESM-Unterstützung in Ihren Tests aktivieren.

  1. Stellen Sie sicher, dass Sie entweder Code-Transformationen deaktivieren, indem Sie transform: {} übergeben, oder konfigurieren Sie Ihren Transformer so, dass er ESM statt des Standard-CommonJS (CJS) ausgibt.

  2. Führen Sie node mit --experimental-vm-modules aus, z.B. node --experimental-vm-modules node_modules/jest/bin/jest.js oder NODE_OPTIONS="$NODE_OPTIONS --experimental-vm-modules" npx jest usw.

    Unter Windows können Sie cross-env verwenden, um Umgebungsvariablen setzen zu können.

    Wenn Sie Yarn verwenden, können Sie yarn node --experimental-vm-modules $(yarn bin jest) nutzen. Dieser Befehl funktioniert auch bei Verwendung von Yarn Plug'n'Play.

    Wenn Ihr Codebase ESM-Imports aus *.wasm-Dateien enthält, müssen Sie --experimental-wasm-modules nicht an node übergeben. Die aktuelle Implementierung von WebAssembly-Imports in Jest basiert auf experimentellen VM-Modulen, dies könnte sich jedoch in Zukunft ändern.

  3. Darüber hinaus versuchen wir, der Logik von node für die Aktivierung des "ESM-Modus" zu folgen (z.B. durch Prüfung von type in package.json oder .mjs-Dateien). Details finden Sie in deren Dokumentation.

  4. Wenn Sie andere Dateiendungen (wie .jsx oder .ts) als ESM behandeln möchten, verwenden Sie die Option extensionsToTreatAsEsm.

Unterschiede zwischen ESM und CommonJS​

Die meisten Unterschiede sind in Nodes Dokumentation erklärt. Zusätzlich zu den dort genannten Punkten injiziert Jest eine spezielle Variable in alle ausgeführten Dateien - das jest-Objekt. Um in ESM auf dieses Objekt zuzugreifen, müssen Sie es aus dem Modul @jest/globals importieren oder import.meta verwenden.

import {jest} from '@jest/globals';

jest.useFakeTimers();

// etc.

// alternatively
import.meta.jest.useFakeTimers();

// jest === import.meta.jest => true

Modul-Mocking in ESM​

Da ESM statische import-Anweisungen auswertet, bevor der Code betrachtet wird, funktioniert das Hoisting von jest.mock-Aufrufen, das in CJS stattfindet, nicht für ESM. Um Module in ESM zu mocken, müssen Sie require oder dynamisches import() nach jest.mock-Aufrufen verwenden, um die gemockten Module zu laden - dasselbe gilt für Module, die die gemockten Module laden.

ESM-Mocking wird über jest.unstable_mockModule unterstützt. Wie der Name schon sagt, ist diese API noch in Arbeit. Bitte verfolgen Sie dieses Issue für Updates.

Die Verwendung von jest.unstable_mockModule ist im Wesentlichen dieselbe wie bei jest.mock mit zwei Unterschieden: Die Factory-Funktion ist erforderlich und sie kann synchron oder asynchron sein:

import {jest} from '@jest/globals';

jest.unstable_mockModule('node:child_process', () => ({
execSync: jest.fn(),
// etc.
}));

const {execSync} = await import('node:child_process');

// etc.

Modul-Democking in ESM​

esm-module.mjs
export default () => {
return 'default';
};

export const namedFn = () => {
return 'namedFn';
};
esm-module.test.mjs
import {jest, test} from '@jest/globals';

test('test esm-module', async () => {
jest.unstable_mockModule('./esm-module.js', () => ({
default: () => 'default implementation',
namedFn: () => 'namedFn implementation',
}));

const mockModule = await import('./esm-module.js');

console.log(mockModule.default()); // 'default implementation'
console.log(mockModule.namedFn()); // 'namedFn implementation'

jest.unstable_unmockModule('./esm-module.js');

const originalModule = await import('./esm-module.js');

console.log(originalModule.default()); // 'default'
console.log(originalModule.namedFn()); // 'namedFn'

/* !!! WARNING !!! Don`t override */
jest.unstable_mockModule('./esm-module.js', () => ({
default: () => 'default override implementation',
namedFn: () => 'namedFn override implementation',
}));

const mockModuleOverride = await import('./esm-module.js');

console.log(mockModuleOverride.default()); // 'default implementation'
console.log(mockModuleOverride.namedFn()); // 'namedFn implementation'
});

Mocking von CommonJS-Modulen​

Für das Mocking von CommonJS-Modulen sollten Sie weiterhin jest.mock verwenden. Siehe Beispiel unten:

main.cjs
const {BrowserWindow, app} = require('electron');

// etc.

module.exports = {example};
main.test.cjs
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.