Ответ 1
Так что это было немного сложно, чтобы работать. Решение довольно простое, но мне потребовалось некоторое время, чтобы заставить его работать. Проблема в том, что всякий раз, когда вы используете какой-либо модуль в шутку
- Файлы настроек
- Файлы рамочной программы установки
- Тестовые файлы
- Файлы модулей
Все они загружены ниже.
({ "Object.": function (module, export, require, __ dirname, __ filename, global, jest) { /* Код модуля внутри */}});
Если вы посмотрите 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);
предоставляет каждому модулю пользовательский требуемый объект. Таким образом, вы, как таковые, не получаете родную функцию require вообще. После того, как начнется шутка, каждый загруженный из него модуль будет иметь функцию jest custom require
.
Когда мы загружаем модуль, вызываются методы requireModule
из jest-runtime
. Ниже приведена выдержка из того же
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);
}
Как вы можете видеть, если расширение файла .node
, он загружает модуль напрямую, иначе он вызывает _execModule
. Эта функция является тем же самым кодом, который я опубликовал ранее, что делает преобразование кода
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);
Теперь, когда мы хотим изменить функцию require
для нашего теста, нам нужно _execModule
экспортировать наш код напрямую. Таким образом, код должен быть похож на загрузку модулей .node
} else if ((_path || _load_path()).default.extname(modulePath) === '.mjs') {
// $FlowFixMe
require = require("@std/esm")(localModule);
localModule.exports = require(modulePath);
} else {
Но это будет означать исправление кода, которого мы хотим избежать. Итак, вместо этого мы избегаем непосредственного использования команды jest и создаем собственный jestload.js
и запускаем это. Код для загрузки шутки прост
#!/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');
Теперь мы хотим изменить _execModule
перед загрузкой cli. Поэтому мы добавляем ниже код
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');
Теперь время для теста
//__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);
});
И файл sum.mjs
export function sum (x, y) { return x + y }
Теперь мы запускаем тест
Решение доступно ниже для репо
https://github.com/tarunlalwani/jest-overriding-require-function-stackoverflow
Вы можете клонировать и тестировать решение, запустив npm test
.