javascript - 在 Jest 中重置 Node 模块

标签 javascript node.js unit-testing jestjs

我有一个 Node.js 应用程序,其中 index.js 对于类 Unix 平台和 Windows 平台有不同的导出。

import os from "os";

function throwNotSupportedError() {
  throw new Error("Platform not supported.");
}

console.log(os.platform());

switch (os.platform()) {
  case "darwin":
  case "linux":
    module.exports = {
      foo: require("./unix/foo"),
      bar: require("./unix/bar")
    };
    break;
  case "win32":
    module.exports = {
      foo: require("./win32/foo"),
      bar: require("./win32/bar")
    };
    break;
  default:
    throwNotSupportedError();
}

我试图用单元测试覆盖这个文件,如下所示:

import os from "os";

jest.mock("os");

describe("Linux platform", () => {
  test("has `foo` and `bar` methods on Linux platform", () => {
    os.platform.mockImplementation(() => "linux");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

describe("Windows platform", () => {
  test("has `foo` and `bar` methods on Windows platform", () => {
    os.platform.mockImplementation(() => "win32");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

问题是 os.platform.mockImplementation(() => "win32"); 可以工作,但是 console.log(os.platform()); 仍然有效即使我在每个测试用例中导入应用程序,也会显示 linux const app = require("../src");

我的错误在哪里以及如何解决?

最佳答案

Khang关于jest.resetModules()的回答正在指向正确的方向。我想补充一点,当您重置模块时,对任何过去导入的引用都将被“忽略”(重置后会创建一个新实例)。换句话说,模块重置后,测试顶部的 import os from "os"; 将不再使用。

解决方案

除了 jest.resetModules()您需要在要执行的测试中重新导入(或在本例中重新要求)os 模块。通过这样做,os.platform.mockImplementation(() => "win32"); 将应用于模块模拟的最新实例。您的两个测试都需要以这种方式构建;

test("has `foo` and `bar` methods on Windows platform", () => {
  const os = require('os');
  os.platform.mockImplementation(() => "win32");

  const app = require("./os-test");
  expect(app.foo).toBeTruthy();
  expect(app.bar).toBeTruthy();
});

您可能需要使用 beforeEach 而不是 afterEach,以确保 os 模块在测试之前是干净的。 Jest 应该隔离每个测试文件,但安全总比后悔好?最后,您希望让 beforeEach 在所有测试之前运行,而不仅仅是在“Windows 平台”describe 内运行。为此,您可以将其移动到文件的根目录,或者将两个 describe 包装在另一个 describe 中,例如

jest.mock("os");

describe('Platform specific module', () => {
  beforeEach(() => {
    jest.resetModules();
  });

  describe("Linux platform", () => {
    test("has `foo` and `bar` methods on Linux platform", () => {
      const os = require('os');
      os.platform.mockImplementation(() => "linux");
      ...

我希望这有帮助! mock 往往很棘手,不仅仅是在 Jest 中。

引用文献

关于javascript - 在 Jest 中重置 Node 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56921304/

相关文章:

node.js - 如何调试 Angular 通用?

node.js - 从交互式命令行 session 中保存 nodejs 历史记录

node.js - 如何 Promisify 使用 NodeJS Bluebird 创建的常规函数​​?

unit-testing - 使用 Moq 模拟返回 IQueryable<MyObject> 的存储库

java - 如何使用 Dagger 模块和 Robolectric 测试 Activity onResume() 上的模拟交互?

javascript - 比较两个数组并找出丢失/错误的项目

javascript - 无法在 javascript 脚本标记内输出实际的 json 数据

用于格式化文本的 JavaScript 函数

ruby-on-rails - 模拟外部 API

javascript - d3 动画导致行为缓慢