我有一个 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/