如何在Jest中为每个测试用例覆盖对象Mock(Mobx Store场景)
解决Jest中单个测试用例覆盖Mobx Store Mock的问题
为什么你的方法不生效
jest.mock()会被Jest自动提升到文件顶部执行,不管你把它写在测试用例里的哪个位置。所以测试用例内的jest.mock()其实是在初始Mock之后运行,但模块已经被缓存,不会重新加载,自然无法覆盖原有Mock。
正确的解决方案
下面提供两种常用的可行方案,根据你的场景选择:
方案1:直接修改Mock对象的属性(推荐,简单高效)
因为你Mock的是一个对象(Mobx Store实例),可以直接在测试用例中修改它的属性,无需重新调用jest.mock()。
示例代码:
import { obj } from "./filepath/obj"; // 初始全局Mock jest.mock("./filepath/obj", () => ({ obj: { search: jest.fn(), items: [1,2,3] } })); // 每个测试用例后重置状态,避免互相影响 afterEach(() => { obj.items = [1,2,3]; // 恢复初始值 obj.search.mockClear(); // 清空函数调用记录 }); test("测试初始items长度", () => { expect(obj.items.length).toBe(3); }); test("测试空items场景", () => { // 直接修改Mock对象的属性 obj.items = []; // 如果需要修改search的返回值,也可以直接mock obj.search.mockReturnValue("搜索结果"); expect(obj.items.length).toBe(0); expect(obj.search()).toBe("搜索结果"); });
方案2:使用jest.resetModules()动态导入模块
如果需要完全替换整个Mock导出(比如替换成不同的对象结构),可以在每个测试用例中重置模块缓存,再重新Mock并导入。
示例代码:
test("测试初始items长度", () => { jest.mock("./filepath/obj", () => ({ obj: { search: jest.fn(), items: [1,2,3] } })); const { obj } = require("./filepath/obj"); expect(obj.items.length).toBe(3); }); test("测试空items场景", () => { jest.resetModules(); // 清空之前的模块缓存 jest.mock("./filepath/obj", () => ({ obj: { search: jest.fn(), items: [] } })); const { obj } = require("./filepath/obj"); expect(obj.items.length).toBe(0); });
注意事项
- 如果你的Mobx Store是通过
observable包装的对象,直接修改属性依然生效,因为Mock的是导出的引用,不需要额外调用Mobx的API。 - 方案1中一定要记得在
afterEach里重置Mock状态,否则测试用例会互相干扰。
内容的提问来源于stack exchange,提问作者sjsouvik
相关产品推荐
相关产品推荐

