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

Vitest中如何断言自定义组合式函数内调用了useHead?

断言组合式函数内部对useHead()的调用

核心解决方案

问题出在模块mock的处理逻辑上,只需确保你的组合式函数导入的useHead是Vitest mock后的版本,无需额外创建spy对象。正确的测试代码如下:

import { useHead } from '@vueuse/head'
import myComposableThatCallsUseHead from 'path/to/composable'

// 自动mock整个@vueuse/head模块,所有导出都会被替换为vi.fn()
vi.mock('@vueuse/head')

describe('myComposableThatCallsUseHead', () => {
  beforeEach(() => {
    // 每次测试前重置mock调用记录,避免测试间数据污染
    vi.clearAllMocks()
  })

  it('调用useHead并传入正确参数', () => {
    // 执行目标组合式函数
    myComposableThatCallsUseHead()

    // 直接断言mock后的useHead函数的调用情况
    expect(useHead).toHaveBeenCalledWith({ title: 'foobar' })
    // 若只需匹配部分参数,可使用如下写法
    // expect(useHead).toHaveBeenCalledWith(expect.objectContaining({ title: 'foobar' }))
  })
})

为什么之前的写法无效?

  • vi.spyOn仅适用于监听对象的方法,独立函数无法通过这种方式捕获调用,因为spyOn需要挂载到某个对象的属性上。
  • 把useHead包裹到自定义对象里创建spy,只会监听该对象上的方法调用,而组合式函数内部导入的是原始模块的useHead,两者不是同一个引用,因此无法捕获实际调用。

关键细节说明

  • vi.mock('@vueuse/head')会自动替换模块内所有导出为mock函数,组合式函数里的import { useHead } from '@vueuse/head'会直接拿到这个mock版本,调用行为自然会被捕获。
  • 如果需要自定义mock的实现逻辑(比如返回特定值),可以这样编写:
vi.mock('@vueuse/head', () => ({
  useHead: vi.fn((options) => { /* 自定义执行逻辑 */ })
}))
  • 每次测试前调用vi.clearAllMocks()是为了清空历史调用记录,保证单个测试用例的独立性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:25:32