如何用Jest测试Vue计算属性中调用的Props函数是否被调用
如何测试Vue计算属性中调用的Props函数是否被执行
首先,你遇到的问题核心在于没有正确使用Jest的mock函数来追踪函数调用,而且测试写法也不符合Vue组件测试的正确姿势。咱们一步步来解决:
关键思路
要验证props中的函数是否被计算属性调用,你需要:
- 用Jest创建一个mock函数(这个函数自带调用追踪能力),替代组件props里的
myFunction - 挂载组件时把这个mock函数传进去
- 触发计算属性的执行,然后断言mock函数是否被调用
完整测试示例
假设你的组件代码是这样的(修正了原示例里的小问题,比如myFunction调用时要加this.):
<template> <!-- 组件模板 --> </template> <script> export default { props: { myFunction: { type: Function, default: () => null }, data: { type: Boolean, default: true } }, computed: { myComputed() { return this.data ? this.myFunction(this.data) : null } } } </script>
对应的Jest测试代码应该这么写:
import { shallowMount } from '@vue/test-utils' import MyComponent from '@/components/MyComponent.vue' describe('MyComponent', () => { it('calls myFunction when data is true', () => { // 1. 创建Jest mock函数 const mockMyFunction = jest.fn() // 2. 挂载组件,传入mock函数作为props const wrapper = shallowMount(MyComponent, { props: { myFunction: mockMyFunction, data: true // 设置data为true,触发计算属性调用函数 } }) // 3. 访问计算属性,触发它的执行 wrapper.vm.myComputed // 4. 断言mock函数被调用,并且传入了正确的参数 expect(mockMyFunction).toHaveBeenCalled() expect(mockMyFunction).toHaveBeenCalledWith(true) }) it('does NOT call myFunction when data is false', () => { const mockMyFunction = jest.fn() const wrapper = shallowMount(MyComponent, { props: { myFunction: mockMyFunction, data: false } }) wrapper.vm.myComputed expect(mockMyFunction).not.toHaveBeenCalled() }) })
你之前写法的问题分析
expect(component.props().myFunction()).toHaveBeenCalled():- 这里你直接调用了
myFunction(),这会执行函数本身,而不是检查它是否被计算属性调用。而且如果myFunction不是mock函数,它根本没有toHaveBeenCalled方法,这就是你看到expect(...).hasBeenCalled is not a function错误的原因。
- 这里你直接调用了
component.computed.myComputed.call({myFunction : () => 0}):- 这种方式手动调用计算属性,但没有绑定正确的组件上下文,而且传入的是普通函数,依然无法追踪调用情况。
额外提示
如果你的计算属性依赖的是组件内部的响应式data,当你修改数据后,需要等待Vue更新DOM和计算属性,这时候要用到await wrapper.vm.$nextTick():
it('calls myFunction when reactive data changes', async () => { const mockMyFunction = jest.fn() const wrapper = shallowMount(MyComponent, { props: { myFunction: mockMyFunction }, data() { return { internalData: false } } }) // 修改响应式数据 wrapper.vm.internalData = true await wrapper.vm.$nextTick() // 等待Vue更新 expect(mockMyFunction).toHaveBeenCalled() })
内容的提问来源于stack exchange,提问作者Axel Moriceau
相关产品推荐
相关产品推荐

