Vitest+Vue Testing Library多测试用例Mock不同数据报错求解决方案
解决Vitest中为不同测试用例设置独立Mock数据的问题
问题根源分析
你遇到的问题核心有两个:
- 笔误导致Mock未正确重置:
beforeEach里调用的是useDivisionWidgetsQuery.mockReset(),但实际Mock的是useQuery1,这使得第一个测试的Mock数据残留到第二个测试中,引发数据混乱。 - 未处理异步查询的渲染时机:组件中
useQuery1是异步逻辑,直接用screen.getByText同步查询DOM时,可能还未完成数据渲染,从而触发错误。
修正后的测试代码
vi.mock('@/dashboard/queries/useQuery1') describe('Widget1', () => { beforeEach(() => { // 正确重置目标Mock,确保每个测试的Mock状态独立 useQuery1.mockReset() }) test('test 1: 显示Future标题', async () => { // 使用mockResolvedValue而非once,确保组件内所有调用都返回该数据 useQuery1.mockResolvedValue({ data1: { amount: 0, date: '2021-01-01', }, data2: { amount: 0 }, data3: { amount: 0 }, data4: { amount: 0 }, data5: { total: 0, url: 'https://www.google.com', }, }) render(Widget1, { props: props, }) // 使用findByText异步查询,等待异步渲染完成 const futureTitle = await screen.findByText('Future') expect(futureTitle).toBeInTheDocument() }) test('test 2: 不显示Future标题', async () => { useQuery1.mockResolvedValue({ data1: null, // 自定义的Mock数据 data2: { amount: 0 }, data3: { amount: 0 }, data4: { amount: 0 }, data5: { total: 0, url: 'https://www.google.com', }, }) render(Widget1, { props: props, }) // 用waitFor配合queryByText,确保组件渲染完成后元素确实不存在 await waitFor(() => { expect(screen.queryByText('Future')).not.toBeInTheDocument() }) }) })
关键修正点说明
- 修正Mock重置对象:将
useDivisionWidgetsQuery.mockReset()改为useQuery1.mockReset(),确保每次测试前清空Mock的调用记录和返回值,避免跨测试污染。 - 替换
mockResolvedValueOnce为mockResolvedValue:如果组件内多次调用useQuery1,mockResolvedValueOnce只会生效一次,后续调用会返回undefined导致组件报错。mockResolvedValue会让所有调用都返回指定数据,更适合单测试用例的独立Mock场景。 - 异步DOM查询处理:
await screen.findByText:这是Vue Testing Library推荐的异步查询方式,会自动等待元素出现(默认超时1000ms)。waitFor + queryByText:getByText在元素不存在时会直接抛出错误,而queryByText会返回null,配合waitFor可以确保组件渲染完成后元素确实不存在。
额外注意事项
- 如果
useQuery1基于TanStack Query(原React Query),可以在测试中给每个用例创建独立的QueryClient实例并包裹QueryClientProvider,避免跨测试的缓存污染。 - 若仍有问题,可在
beforeEach中用useQuery1.mockImplementation(() => ({ isLoading: false, data: ... }))显式定义Mock的返回结构,确保组件能正确解构数据。
内容的提问来源于stack exchange,提问作者Yz_
相关产品推荐
相关产品推荐

