Vitest断言失败:Vue组件调用Axios请求后DOM未更新
Vue组件Axios请求功能正常,但Vitest测试无法检测到文本更新
点击按钮后,div文本通过Axios请求返回的数据更新,实际功能正常,但Vitest测试失败(测试中div文本未更新)。已知then代码块已执行(控制台打印了更新后的dataToDisplay值),尝试过await nextTick()、flushPromises()、setTimeout()均无效。
组件代码(Component.js)
<template> <button data-testid="button" @click="getData"> Get data </button> <div>{{dataToDisplay}}</div> </template> <script setup> import {ref} from 'vue'; import axios from 'axios'; const dataToDisplay = ref(''); function getData() { axios.post('/route') .then((response) => { dataToDisplay.value = response.data; console.log(dataToDisplay.value); }) } </script>
原测试代码(Component.test.js)
import { render, fireEvent } from '@testing-library/vue'; import axios from 'axios'; vi.mock('axios'); test('text is rendered from axios request', async () => { const { queryByTestId, getByText } = render(Component); axios.post.mockResolvedValue({ status: 200, data: 'new text', }); fireEvent.click(queryByTestId('button')); await nextTick(); getByText('new text'); });
解决方案
问题出在测试未正确等待异步请求完成及DOM更新时机,修正方案如下:
1. 等待点击触发的异步操作完成
fireEvent.click返回Promise,使用await等待它完成,确保Axios请求的Promise已resolve、数据已更新。
2. 使用waitFor包裹断言
waitFor会反复执行回调直到断言成功或超时,确保DOM完成更新后再进行断言。
修正后的测试代码
import { render, fireEvent, waitFor } from '@testing-library/vue'; import axios from 'axios'; import Component from './Component.vue'; vi.mock('axios'); test('text is rendered from axios request', async () => { const { queryByTestId, getByText } = render(Component); axios.post.mockResolvedValue({ status: 200, data: 'new text', }); // 等待点击事件触发的所有异步逻辑完成 await fireEvent.click(queryByTestId('button')); // 等待DOM更新后断言文本存在 await waitFor(() => { getByText('new text'); }); });
原因说明
nextTick仅等待Vue的DOM更新周期,但如果Axios的Promise还未resolve,此时数据并未更新,nextTick执行后断言依然失败。await fireEvent.click会等待点击事件相关的所有异步操作(包括Axios请求的Promise)完成,确保数据已更新到响应式变量中。waitFor会处理DOM更新的延迟,确保断言时目标文本已渲染到页面上。
内容的提问来源于stack exchange,提问作者Cal El
相关产品推荐
相关产品推荐

