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直接模拟整个模块:
- 新建工具模块(比如
utils/hello.js):
export function sayHello(text) { console.log(text) }
- 组件中导入并使用:
import { sayHello } from '@/utils/hello' export default defineComponent({ setup() { function greet(text) { sayHello(text) } return { greet } } })
- 测试时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
相关产品推荐
相关产品推荐

