如何在Vitest中测试Vue3 Watch触发的函数?
解决Vue3组件中Vitest测试watch触发的问题
问题根源
你在<script setup>中声明的page、doCaseSearch都是组件内部私有成员,默认不会挂载到组件实例(wrapper.vm)上,所以直接通过wrapper.vm.page修改值或者监听wrapper.vm.doCaseSearch都会失效。
正确实现方法
方法1:通过defineExpose暴露测试所需的成员
先修改组件代码,把需要测试的变量和函数暴露给外部:
<script setup> import { ref, watch } from 'vue' const page = ref(1) const size = ref(25) const sort = ref(new Array<Order>()) // 修正原代码语法错误:移除多余的> const searchProps = ref(/* 你的初始值 */) const doCaseSearch = (props) => { // 你的业务逻辑实现 } watch([page, size, sort], () => doCaseSearch(searchProps.value)) // 暴露给测试用例 defineExpose({ page, doCaseSearch, searchProps // 如需验证传参可一并暴露 }) </script>
然后编写测试用例:
import { mount, flushPromises } from '@vue/test-utils' import { vi } from 'vitest' import YourComponent from './YourComponent.vue' it('should call doCaseSearch when page changes', async () => { const wrapper = mount(YourComponent) // 获取暴露的成员 const { page } = wrapper.vm // 创建函数 spy const doCaseSearchSpy = vi.spyOn(wrapper.vm, 'doCaseSearch') // 修改响应式变量的值 page.value = 7 // 等待watch回调及响应式更新完成 await flushPromises() // 断言函数调用次数 expect(doCaseSearchSpy).toHaveBeenCalledTimes(1) // 可选:验证传入参数是否正确 // expect(doCaseSearchSpy).toHaveBeenCalledWith(wrapper.vm.searchProps.value) })
方法2:模拟用户交互触发page变化(无需修改组件)
如果不想暴露组件内部成员,可以通过模拟用户操作触发page变化。假设组件内有分页按钮,点击对应按钮会修改page值:
it('should call doCaseSearch when page changes via user interaction', async () => { const wrapper = mount(YourComponent) // 假设分页按钮的选择器为`.pagination-btn[data-page="7"]` await wrapper.find('.pagination-btn[data-page="7"]').trigger('click') await flushPromises() // 可通过断言组件状态变化或外部依赖调用情况验证逻辑,比如mock接口后断言调用 })
补充说明
- 原组件代码中
const sort = ref(new Array<Order>()>存在语法错误,需修正为const sort = ref(new Array<Order>())。 flushPromises()用于等待watch回调(若含异步逻辑)和响应式更新完成,确保断言时机正确。
内容的提问来源于stack exchange,提问作者S Huff
相关产品推荐
相关产品推荐

