使用 Jest 在 Node 中模拟动态需求

Eri*_*ikE 4 mocking node.js jestjs

给定一个需要从父/引用包的根动态加载依赖项的 npm 包,并且该位置直到运行时才知道,它必须执行动态要求:

// config-fetcher.js
const path = require('path');
const getRunningProjectRoot = require('./get-running-project-root');'
module.exports = filename =>
   require(path.resolve(getRunningProjectRoot(), filename));
Run Code Online (Sandbox Code Playgroud)

(不能保证模块会在node_modules. 它可以被符号链接或全局加载。所以它不能使用静态需求。)

这是从实际代码中简化的,因此除非您知道一种相对于正在运行的项目根目录非动态地要求文件的方法,否则必须采用这种方式。

现在,为了测试这一点,我不想依赖任何实际在磁盘上的文件。然而,Jest 似乎不会让你模拟一个不存在的文件。所以如果我试试这个:

const mockFileContents = {};
jest.mock('/absolute/filename.blah', () => mockFileContents);
// in preparation for wanting to do this:
const result = require('./config-fetcher')('/absolute/filename.blah');
expect(result).toBe(mockFileContents);
Run Code Online (Sandbox Code Playgroud)

然后我收到一个错误jest-resolve,文件Resolver.resolveModule抛出Error: Cannot find module '/absolute/filename.blah'.

我需要测试这个动态需求模块的一些功能,因为它处理相对路径与绝对路径的一些情况,并允许您通过符号指定一个特殊路径,例如一个 applicationRoot,所以该模块config-fetcher执行努力工作而不是来电者。

任何人都可以提供有关如何测试此模块或如何重组以便不需要动态需求或它们更易于测试的指导吗?

Bri*_*ams 14

您可以通过{ virtual: true }optionsjest.mock嘲笑那个不存在的模块:

const { myFunc } = require('does not exist');

jest.mock('does not exist',
  () => ({
    myFunc: () => 'hello'
  }),
  { virtual: true }
);

test('mock file that does not exist', () => {
  expect(myFunc()).toBe('hello');  // Success!
});
Run Code Online (Sandbox Code Playgroud)

细节

Jest完全接管require被测代码的系统。

它有自己的模块缓存并跟踪模块模拟。

作为该系统的一部分,Jest允许您为实际不存在的模块创建模拟。

您可以将options第三个参数传递给jest.mock. 目前唯一的选项是virtual,如果是,true则将Jest调用模块工厂函数的结果简单地添加到模块缓存中,并在被测代码中需要时返回它。