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

如何在Jest每个测试用例中重置导入JSON文件的动态mock

问题原因
  • jest.mock 存在自动提升(hoist)特性,所有jest.mock调用会在测试文件初始化阶段优先执行,写在测试用例内部的多个jest.mock会被统一提升到顶部,最终只会保留最后一个的实现,因此只有首个测试用例的mock看起来生效。
  • jest.resetAllMocks() 仅用于清除mock函数的调用记录、重置返回值等配置,不会清除Jest的模块缓存,也不会修改已注册的模块mock实现,因此对你的场景无效。
  • 如果你在测试文件顶部静态导入了业务方法,业务方法依赖的JSON文件已经被模块缓存,后续修改mock也不会更新已经导入的JSON值。
  • 你使用await import动态导入JSON,属于ES模块导入规范,导入结果是模块对象,JSON内容存在于default属性下,mock时需要匹配这个结构。
解决方案

推荐两种实现方式,按需选择即可:

方案1:可变变量mock(写法最简洁)

在测试文件顶层先完成JSON的mock,指向一个可变变量,每个测试用例直接修改这个变量的值即可:

// 测试文件顶部,定义可变的mock变量
let mockItems = []
// 匹配ES模块导入结构,返回default属性
jest.mock('../assets/items.json', () => ({
  default: mockItems
}))
// 可以直接静态导入需要测试的业务方法
import { selectQuery } from '你的业务代码文件路径'

it('test A', () => {
  mockItems = [1,2,3]
  const expectedItems = selectQuery('...items')
  expect(expectedItems).toEqual(mockItems)
})

it('test B', () => {
  mockItems = [3,4,5]
  const expectedItems = selectQuery('...items')
  expect(expectedItems).toEqual(mockItems)
})

方案2:动态导入+清空模块缓存

如果不想使用全局可变变量,可以通过jest.doMock+jest.resetModules实现每个测试用例独立mock:

// 不要在顶部导入业务方法
beforeEach(() => {
  // 每次测试前清空所有模块缓存,保证每次导入都是最新的mock结果
  jest.resetModules()
})

it('test A', async () => {
  const itemsA = [1,2,3]
  // 用doMock代替mock,不会被提升,仅当前用例生效
  jest.doMock('../assets/items.json', () => ({
    default: itemsA
  }))
  // 动态导入业务方法,此时内部依赖的JSON是当前mock的结果
  const { selectQuery } = await import('你的业务代码文件路径')
  const expectedItems = selectQuery('...items')
  expect(expectedItems).toEqual(itemsA)
})

it('test B', async () => {
  const itemsB = [3,4,5]
  jest.doMock('../assets/items.json', () => ({
    default: itemsB
  }))
  const { selectQuery } = await import('你的业务代码文件路径')
  const expectedItems = selectQuery('...items')
  expect(expectedItems).toEqual(itemsB)
})

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:12:02