Jest中模拟动态的Node require功能

7

假设有一个需要从父级/引用包的根目录动态加载依赖项的npm包,且该位置在运行时未知,则必须执行动态require操作:

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

(不能保证模块将出现在 node_modules 中。它可能是符号链接或全局加载的。因此,它不能使用静态 require。)

这是从实际代码简化而来的,所以除非你知道一种相对于正在运行的项目根目录非动态地要求文件的方法,否则只能采用这种方式。

现在,为了测试这个,我宁愿不依赖任何实际上存在于磁盘上的文件。但是,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);

然后我收到了来自 jest-resolve 的错误,文件为 Resolver.resolveModule,报错信息为 Error: Cannot find module '/absolute/filename.blah'.

我需要测试这个动态导入模块的一些功能,因为它处理了一些相对路径和绝对路径的情况,并且允许您通过符号指定一个特殊路径,例如 applicationRoot,所以模块 config-fetcher 负责较难的工作而不是调用者。

有没有人能够提供如何测试此模块或如何重新结构化使得动态导入不再需要或更容易被测试的指导?

1个回答

23

jest.mock中,您可以将{ virtual: true }作为options传递进去,以模拟一个不存在的模块:

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!
});

详情

Jest完全接管了被测试代码所需的require系统。

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

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

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


需要帮助:https://dev59.com/lHcPtIcB2Jgan1znFQqJ - micronyks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接