用 Jest 重置单个模块

Posted

技术标签:

【中文标题】用 Jest 重置单个模块【英文标题】:Reset single module with Jest 【发布时间】:2018-01-16 05:31:09 【问题描述】:

jest.resetModules() 清除所有模块的 require 缓存,但有没有办法只为单个模块清除它?无法使用 require.cache,因为 Jest 似乎绕过了它。

我正在测试一个有状态的 Node 模块(即它依赖于对 require 的多次调用返回相同实例的事实)。对于我的测试,我需要重置模块的状态以测试不同的场景。 jest.resetModules() 有效,但我需要重新require 其他一些不需要重置的模拟模块。

【问题讨论】:

目前无法查看源代码。 resetModules 完全空白 _moduleRegistry 并且您无法从测试上下文中访问它。我想说它需要一种新方法添加到可以从注册表中删除单个模块的上下文中。我建议在 repo 上打开和发布,希望他们能够使用此功能更新 jest。 如果有意义,您可以隔离您的有状态模块并单独使用resetModules() 对其进行测试。 也许您可以像这样加载单个模块:jest.mock( '../moduleName', () => const myModule = importFresh('/path/to/module') , virtual: true, );?这将允许您加载模块的新副本,从而有效地重置模块以进行测试。 importFresh来自github.com/sindresorhus/import-fresh 关注此线程github.com/facebook/jest/issues/6174 似乎仍然是一个悬而未决的问题/改进。还有一个用于范围模块初始化的开放 PR。在这里查看:github.com/facebook/jest/pull/6701 但是任何足够成熟并且可以立即使用的东西...... Jest 创建了自己的 require 钩子,主要用于保持全局 require 缓存干净并避免副作用。从你的所作所为听起来你只需要模拟你想要使用的模块,然后确保你在 describe 块的末尾清除它,你不应该把模拟模块放在周围供其他测试使用。如果你正确地设置和拆除你的模拟,你不应该遇到这个问题。你能提供一个更好的例子吗? 【参考方案1】:

自 Jest 24 起,您现在可以使用 jest.isolateModules 来执行此操作。

假设你只想重置某个模块,那么你应该在jest.isolateModules的回调中要求:

let myModule;
jest.isolateModules(() => 
  myModule = require('my-certain-module');
);

【讨论】:

我们能得到一个扩展的例子吗?这类似于 jest 文档,它没有明确说明发生了什么或如何使用它 imo【参考方案2】:

为某些测试模拟模块(带有工厂)并在测试文件中恢复其他模块的示例

describe("some tests", () => 
  let subject;

  describe("with mocks", () => 
    beforeAll(() => 
      jest.isolateModules(() => 
        jest.doMock("some-lib", () => ( someFn: jest.fn() )); // .doMock doesnt hoist like .mock does when using babel-jest
        subject = require('./module-that-imports-some-lib');
      );
    );

    // ... tests when some-lib is mocked
  );

  describe("without mocks - restoring mocked modules", () => 
    beforeAll(() => 
      jest.isolateModules(() => 
        jest.unmock("some-lib");
        subject = require('./module-that-imports-some-lib');
      );
    );

    // ... tests when some-lib is NOT mocked

  );
);

【讨论】:

以上是关于用 Jest 重置单个模块的主要内容,如果未能解决你的问题,请参考以下文章

用 Jest 模拟 Lerna 范围模块

用 Jest 测试 ES6 模块

在使用 jest 的 vue 测试中找不到模块“@jest/globals”

用 Jest 模拟基于承诺的请求

Jest,ts-jest,带有 ES 模块导入的打字稿:找不到模块

React Native Expo - Jest - React Native Firebase - Invariant Violation:Native 模块不能为空