如何在Jest中模拟函数依赖,使被调用函数生效?
解决Jest Mock函数a无法影响函数b调用的问题
问题核心:原模块中函数b调用的是内部定义的a函数,而非模块导出的a引用。你mock的只是模块对外导出的a,但b执行时根本没用到这个导出版本,所以mock不会生效。
方案一:修改原代码,让b依赖导出的a
这是最符合模块化规范的做法,让模块内部函数通过导出对象引用,测试时mock导出成员就能覆盖调用:
修改myFunctions.js:
// 方式1:直接引用exports对象 function a() { return 5; } function b() { return exports.a() + 5; // 使用导出的a } module.exports = { a, b };
或者更清晰地用统一导出对象:
// 方式2:提前定义导出对象 const functions = { a: () => 5, b: () => functions.a() + 5 // 引用同一对象内的a }; module.exports = functions;
此时你的原测试代码就能正常工作,第二个测试会通过——因为b现在调用的是你mock后的导出版a。
方案二:在Jest Mock中重新定义b(无需修改原代码)
如果不想改动原代码,可以在jest.mock中重新实现b,让它绑定mock的a:
const { a, b } = require("./myFunctions"); jest.mock("./myFunctions", () => { const mockA = jest.fn(() => 10); return { a: mockA, b: () => mockA() + 5 // 手动让b依赖mock的a }; }); describe("myFunctions", () => { it("mocks a", () => { expect(a()).toEqual(10); }); it("mock affects b", () => { expect(b()).toEqual(15); }); });
注意:这种方法需要在测试中同步维护b的实现,原代码修改后测试也要跟着调整,灵活性较差。
方案三:用jest.spyOn动态替换导出的a(配合原代码调整)
如果原代码已经改成让b依赖导出的a,也可以用spyOn动态mock并在测试后恢复:
const myFunctions = require("./myFunctions"); describe("myFunctions", () => { afterEach(() => { jest.restoreAllMocks(); // 测试结束后恢复原函数 }); it("mocks a and affects b", () => { jest.spyOn(myFunctions, "a").mockReturnValue(10); expect(myFunctions.b()).toEqual(15); }); });
内容的提问来源于stack exchange,提问作者MikkoP
相关产品推荐
相关产品推荐

