指定在任何Jest安装发生之前运行的代码

Ada*_*kis 26 javascript jestjs

tl;博士是:

1)我怎样才能让Jest使用本机require函数在我的测试中加载所有模块.

2)在任何测试运行之前,我在哪里/如何修改(即用esm加载器替换)https://github.com/standard-things/esm在一个地方使用require函数,所以所有测试都将使用修改过的要求.


我想将esm-loader与我的Jest测试文件一起使用.为了做到这一点,我需要在任何测试代码运行之前全局修补require函数,例如

require = require("@std/esm")(module, { esm: "js", cjs: true });

在触摸或请求任何其他内容之前,如何告诉Jest执行该代码?

我尝试将两者setupTestFrameworkScriptFile和一个setupFiles数组条目指向一个包含它的文件,但都没有工作(尽管我确认两者都运行了).

或者,我用npm脚本启动这些测试

"scripts": {
  "test": "jest"
}
Run Code Online (Sandbox Code Playgroud)

是否有一些CLI魔术,我可以加载模块然后运行jest


编辑 - testEnvironmentresolver选项让我想知道是否甚至使用实际的Node require函数来加载模块,或者使用自己的模块加载器.如果是这样,我想知道这是否可行.

Tar*_*ani 17

所以这个有点难以开始工作.解决方案非常简单,但我需要一段时间才能使其正常运行.问题是每当你在开玩笑中使用任何模块时

  • 设置文件
  • 安装框架文件
  • 测试文件
  • 模块文件

它们都是以下方式加载的

({"Object.":function(module,exports,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]);
Run Code Online (Sandbox Code Playgroud)

this._createRequireImplementation(filename, options);为每个模块提供自定义需求对象.因此,您根本无法在任何地方获得本机需求功能.一旦启动了jest,从那时起加载的每个模块都将具有jest的自定义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);
  }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,文件的扩展名是否.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);
Run Code Online (Sandbox Code Playgroud)

现在,当我们想要修改require测试函数时,我们需要_execModule直接导出代码.所以代码应该类似于加载.node模块

  } else if ((_path || _load_path()).default.extname(modulePath) === '.mjs') {
    // $FlowFixMe
    require = require("@std/esm")(localModule);
    localModule.exports = require(modulePath);
  } else {
Run Code Online (Sandbox Code Playgroud)

但这样做意味着修补我们想要避免的代码.所以我们做的是避免直接使用jest命令,并创建我们自己的jestload.js并运行它.加载jest的代码很简单

#!/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');
Run Code Online (Sandbox Code Playgroud)

现在我们要_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');
Run Code Online (Sandbox Code Playgroud)

现在是时候进行测试了

//__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);
});
Run Code Online (Sandbox Code Playgroud)

还有一个sum.mjs档案

export function sum (x, y) { return x + y }
Run Code Online (Sandbox Code Playgroud)

现在我们进行测试

开玩笑测试

该解决方案可在以下回购中找到

https://github.com/tarunlalwani/jest-overriding-require-function-stackoverflow

您可以通过运行来克隆和测试解决方案npm test.