Więc ten był trochę trudny do pracy. Rozwiązanie jest dość proste, ale zajęło mi trochę czasu, aby działało.Problemem jest to, że przy każdym użyciu dowolnego modułu żartem
- pliki instalatora
- Konfiguracja Framework Pliki Pliki
- test
- Moduł pliki
Wszystkie są ładowane poniżej sposób
({"Obiekt.": Funkcja (moduł, eksport, wymagane, __ nazwa_dokumentu, __ filen ame, global, jest) {/* Kod modułu wewnątrz */ }});
Jeśli spojrzeć na node_modules/jest-runtime/build/index.js:495:510
const dirname = (_path || _load_path()).default.dirname(filename);
localModule.children = [];
localModule.parent = mockParentModule;
localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);
const transformedFile = this._scriptTransformer.transform(
filename,
{
collectCoverage: this._coverageOptions.collectCoverage,
collectCoverageFrom: this._coverageOptions.collectCoverageFrom,
collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom,
isInternalModule,
mapCoverage: this._coverageOptions.mapCoverage },
this._cacheFS[filename]);
this._createRequireImplementation(filename, options);
daje każdy moduł wymaga niestandardowego obiektu. Więc ty jako taki nie masz nigdzie wymagać funkcji, wszędzie. Po rozpoczęciu żartu każdy moduł załadowany od tego momentu będzie miał niestandardową funkcję żartu require
.
Po załadowaniu modułu wywoływane są metody requireModule
z jest-runtime
. Poniżej znajduje się fragment z tego samego
moduleRegistry[modulePath] = localModule;
if ((_path || _load_path()).default.extname(modulePath) === '.json') {
localModule.exports = this._environment.global.JSON.parse(
(0, (_stripBom || _load_stripBom()).default)((_gracefulFs || _load_gracefulFs()).default.readFileSync(modulePath, 'utf8')));
} else if ((_path || _load_path()).default.extname(modulePath) === '.node') {
// $FlowFixMe
localModule.exports = require(modulePath);
} else {
this._execModule(localModule, options);
}
Jak widać, jeśli rozszerzenie pliku jest .node
ładuje moduł bezpośrednio, inny wywołuje _execModule
. Funkcja ta jest ten sam kod, który napisałem wcześniej, który robi transformacji kodu
const isInternalModule = !!(options && options.isInternalModule);
const filename = localModule.filename;
const lastExecutingModulePath = this._currentlyExecutingModulePath;
this._currentlyExecutingModulePath = filename;
const origCurrExecutingManualMock = this._isCurrentlyExecutingManualMock;
this._isCurrentlyExecutingManualMock = filename;
const dirname = (_path || _load_path()).default.dirname(filename);
localModule.children = [];
localModule.parent = mockParentModule;
localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);
Teraz, gdy chcemy zmodyfikować require
funkcję dla naszego testu, musimy _execModule
bezpośredni eksport naszego kodu. Więc kod powinien być podobny do ładunkowej .node
modułów
} else if ((_path || _load_path()).default.extname(modulePath) === '.mjs') {
// $FlowFixMe
require = require("@std/esm")(localModule);
localModule.exports = require(modulePath);
} else {
Ale robi to oznaczałoby łatanie kod, który chcemy uniknąć. Zamiast tego używajmy polecenia dowcip bezpośrednio i stwórzmy własny jestload.js
i uruchommy to. Kod do załadunku żartem jest prosta
#!/usr/bin/env node
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
cli = require('jest/bin/jest');
Teraz chcemy zmodyfikować _execModule
przed CLI obciążeń.Więc dodać poniżej kodu
const jestRuntime = require("jest-runtime");
oldexecModule = jestRuntime.prototype._execModule;
jestRuntime.prototype._execModule = function (localModule, options) {
if (localModule.id.indexOf(".mjs") > 0) {
localModule.exports = require("@std/esm")(localModule)(localModule.id);
return localModule;
}
return oldexecModule.apply(this, [localModule, options]);
};
cli = require('jest/bin/jest');
nadszedł czas na test
//__test__/sum.test.js
sum = require('../sum.mjs').sum;
test('adds 1 + 2 to equal 3',() => {
expect(sum(1, 2)).toBe(3);
});
test('adds 2 + 3 to equal 5',() => {
expect(sum(3, 2)).toBe(5);
});
i plik sum.mjs
export function sum (x, y) { return x + y }
Teraz możemy uruchomić test

Rozwiązaniem jest dostępny na poniżej repo
https://github.com/tarunlalwani/jest-overriding-require-function-stackoverflow
można sklonować i przetestować rozwiązania uruchamiając npm test
.
['transform'] (https://facebook.github.io/jest/docs/en/configuration.html#transform-object-string-string)? –
@ Orb - dzięki, ale nie, niestety. Potrzebuję niższego poziomu. U chcesz zamienić program ładujący węzła głównego na ładowany, który obsługuje ES6. Ale biorąc pod uwagę moją edycję, nie jestem nawet pewien, czy Node używa głównego narzędzia do rozpoznawania węzłów, więc to może nie być możliwe. –
Z twojego użycia skryptu npm, [jest-cli] (https://github.com/facebook/jest /blob/77744a24816d0978b6c478987426c36d615864bd/packages/jest-cli/bin/jest.js) powinien być pierwszą rzeczą, która działa. Możesz spróbować edytować ten plik lokalnie, łatając funkcję require za pomocą 'require (" @ std/esm ")', przed 'require ('../ build/cli'). Run();'. Jeśli to zadziała, możesz przynajmniej potwierdzić, że twój pomysł brzmi dobrze. –