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

使用Vitest遇ReferenceError:无法在初始化前访问mock

解决Vitest中Redis Mock的"Cannot access before initialization"错误

问题原因

Vitest会自动将所有vi.mock调用提升到文件代码执行的最顶部,哪怕你把vi.mock写在setExMock定义之后,实际运行时mock工厂函数会先执行,此时setExMock还未被初始化,因此抛出ReferenceError。

解决方案

方案1:使用vi.hoisted()同步提升mock函数

通过vi.hoisted()包裹mock函数的定义,让它和vi.mock一起被提升到顶部,确保mock执行时变量已初始化:

// 用vi.hoisted()将setExMock和mock一同提升
const { setExMock } = vi.hoisted(() => ({
  setExMock: vi.fn()
}))

vi.mock('redis', () => {
  return {
    createClient: () => {
      return {
        connect: vi.fn(),
        get: vi.fn(),
        setEx: setExMock,
      }
    },
  }
})

// 测试中直接使用setExMock
test('验证setEx调用参数', () => {
  // 执行触发setEx的业务逻辑
  expect(setExMock).toHaveBeenCalledWith('key', 3600, 'value')
})

方案2:在mock工厂内部定义并暴露mock函数

把setExMock定义在mock工厂函数内部,同时通过自定义导出暴露给测试代码:

vi.mock('redis', () => {
  const setExMock = vi.fn()
  return {
    createClient: () => ({
      connect: vi.fn(),
      get: vi.fn(),
      setEx: setExMock,
    }),
    // 自定义导出,供测试用例引用
    __setExMock: setExMock
  }
})

// 测试中导入自定义导出的mock函数
import { __setExMock as setExMock } from 'redis'

test('验证setEx调用参数', () => {
  // 执行业务逻辑
  expect(setExMock).toHaveBeenCalledWith('key', 3600, 'value')
})

说明

两种方案都能解决变量初始化顺序的问题,方案1更贴合你原本的代码结构,无需额外导入;方案2则通过内部定义避免提升问题,适合更复杂的mock场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:20:00