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

Vue 3组合式API+Vue Test Utils 2如何模拟内部调用函数?

Vue3 + Vue Test Utils 2中模拟组件内互相调用的函数

问题出在组合式API的函数作用域上:你在setup里定义的greet直接调用的是作用域内的sayHello函数,而jest.spyOn(wrapper.vm, 'sayHello')监听的是返回给组件实例的那个函数引用——这两个不是同一个对象,所以实际调用时不会触发你的spy,导致调用次数为0。

对比Vue2选项式API:选项式的methods里,greet内部调用的sayHello等价于this.sayHello,也就是实例挂载的方法,所以spy能正常捕获调用。

下面提供两种可行的解决方案:

方案一:让内部调用指向同一个引用对象

修改组件代码,把函数挂载到同一个对象上,让greet通过这个对象调用sayHello:

export default defineComponent({
  setup() {
    const methods = {
      greet(text) {
        methods.sayHello(text) // 调用同一个对象上的sayHello
      },
      sayHello(text) {
        console.log(text)
      }
    }

    return methods
  }
})

测试代码保持你原来的写法即可:

test('should sample', async () => {
  const spy = jest.spyOn(wrapper.vm, 'sayHello')
  wrapper.vm.greet('hello world')
  expect(spy).toHaveBeenCalledWith('hello world')
})

此时wrapper.vm.sayHello和greet内部调用的是同一个函数引用,spy就能正确捕获调用。

方案二:抽离函数为独立模块(推荐用于可复用逻辑)

如果sayHello是通用逻辑,可以把它抽成单独的模块,然后在组件中导入使用,这样就能通过jest.mock直接模拟整个模块:

  1. 新建工具模块(比如utils/hello.js):
export function sayHello(text) {
  console.log(text)
}
  1. 组件中导入并使用:
import { sayHello } from '@/utils/hello'

export default defineComponent({
  setup() {
    function greet(text) {
      sayHello(text)
    }

    return { greet }
  }
})
  1. 测试时mock该模块:
import { sayHello } from '@/utils/hello'
import YourComponent from '@/components/YourComponent.vue'

jest.mock('@/utils/hello', () => ({
  sayHello: jest.fn()
}))

test('should call sayHello with correct text', async () => {
  const wrapper = mount(YourComponent)
  wrapper.vm.greet('hello world')
  expect(sayHello).toHaveBeenCalledWith('hello world')
})

这种方式更符合模块化开发思路,也避免了组件内部函数引用绑定的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:18:18