用Jest在Node中模拟动态需求

时间:2019-05-09 04:08:09

标签: node.js mocking jestjs

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

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

(无法保证模块将位于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);

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

我需要测试此动态需求模块的某些功能,因为它可以处理相对路径与绝对路径的某些情况,并允许您通过符号指定特殊路径,例如{{1 }},因此模块applicationRoot代替了调用者来完成工作。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

有人试过测试动态导入吗?下面的示例代码进行测试。如果我不使用动态导入 jest.mock + virtual: true 有效。

const Routes =  React.lazy(() => import('app2/routes'));

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

test('mock file that does not exist', () => {
  expect(myFunc()).toBe('hello');  // Failed!
});