You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:45:19