NodeJS 使用Jest模拟节点中的动态需求

z2acfund  于 2023-01-16  发布在  Node.js
关注(0)|答案(1)|浏览(131)

给定一个需要从父包/引用包的根目录动态加载依赖项的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'.
我需要测试这个动态请求模块的一些功能,因为它处理相对路径与绝对路径的一些情况,并允许您通过Symbol指定一个特殊的路径,例如applicationRoot,因此模块config-fetcher代替调用者完成了繁重的工作。
有谁能提供一些指导,告诉我们如何测试这个模块,或者如何重新构造,以便不需要动态需求,或者使它们更容易测试吗?

pftdvrlh

pftdvrlh1#

可以在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会简单地将调用模块工厂函数的结果添加到模块缓存中,并在测试代码需要时将其返回。

相关问题