我有一个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");中导入应用程序。
我的错误在哪里,如何解决?
发布于 2019-07-13 12:00:02
张先生对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");
...我希望这能帮到你!嘲笑往往是很棘手的,而不仅仅是在Jest。
参考资料
发布于 2019-07-09 19:48:57
您正在测试范围内模拟os模块,但实际代码在它自己的范围内使用该模块。jest.mock只使用导出的方法并将它们替换为jest.fn,所以理论上,您的代码需要导出os,然后测试代码应该只需要在文件顶部一次。您的测试代码不应该直接导入os。
顺便说一句,这只是一个未经检验的理论,从阅读关于Jest模拟的教程。
发布于 2019-07-10 09:22:41
您需要在每次测试之后使用jest.resetModules()来清除模块缓存:
describe("Windows platform", () => {
afterEach(() => {
jest.resetModules();
})
//...
})https://stackoverflow.com/questions/56921304
复制相似问题