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

Vitest无法Mock被测文件内函数问题求助

同一个模块内Vitest Mock函数不生效的问题解决

你遇到的是同模块内函数无法被Vitest Mock的典型问题,核心原因是模块内部函数调用的是本地引用,而非导出的引用。

问题根源

在test.ts中,foo直接调用的是模块内部的bar变量,不是你通过import * as testFile拿到的导出对象上的bar。vi.spyOn只能mock导出对象上的方法,但foo根本没用到这个导出的引用,所以mock不会生效。

解决方案

方案1:让模块内部通过自身导出调用函数

修改test.ts,让foo通过模块自身的导出引用调用bar,这样mock导出的bar就能影响到foo:

// test.ts
export const bar = () => 'bar'

// 引入自身模块的导出
import * as self from './test'
export const foo = () => `I am foo. bar is ${self.bar()}`

测试代码无需修改,即可正常生效。

方案2:拆分模块(已验证有效)

将bar移到单独模块,彻底隔离依赖:

// utils.ts
export const bar = () => 'bar'
// test.ts
import { bar } from './utils'
export const foo = () => `I am foo. bar is ${bar()}`

测试文件mock独立模块的bar:

import { describe, expect, it, vi } from 'vitest'
import { foo } from './test'
import * as utils from './utils'

describe('module', () => {
  it('foo', () => {
    vi.spyOn(utils, 'bar').mockImplementation(() => 'fake bar')
    expect(foo()).toEqual('I am foo. bar is fake bar')
  })
})

方案3:使用Vitest模块Mock

无需修改原代码,直接mock整个模块的导出:

// test.unit.spec.ts
import { describe, expect, it, vi } from 'vitest'

// 先mock模块,再导入目标函数
vi.mock('./test', () => ({
  // 自定义mock的bar
  bar: vi.fn(() => 'fake bar'),
  // 保留原foo的实现
  ...vi.importActual('./test')
}))

import { foo, bar } from './test'

describe('module', () => {
  it('foo', () => {
    expect(foo()).toEqual('I am foo. bar is fake bar')
    expect(bar).toHaveBeenCalled()
  })
})

内容的提问来源于stack exchange,提问作者Mr.Tr33

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 06:16:01