Vitest中Svelte组件onMount未调用问题求助
问题解决方案
你的测试失败核心原因有两个:onMount异步执行导致测试同步断言时机过早,以及组件内API请求代码存在语法错误,以下是具体修复步骤:
1. 修复组件内的API请求代码
你的Component.svelte中遗漏了将响应解析为JSON的步骤,导致data变量未定义,即使onMount执行也会报错;同时id="#element"多了多余的#,建议修正:
<script> import { onMount } from 'svelte'; export let name = 'world'; onMount(async () => { console.log('chat onMount event!'); const response = await fetch('http://localhost:8081/api'); const data = await response.json(); // 新增:解析响应为JSON name = data.name; }); </script> <div id="element"> <!-- 去掉id里多余的# --> <b> Hello {name}</b> </div>
2. 修改测试代码以支持异步断言
onMount是异步执行的,你的测试代码同步运行时,组件刚渲染完成显示的是默认值Hello world,此时还未完成API请求和状态更新。需要使用异步测试方式,等待异步操作完成后再断言:
方案一:使用findByText(推荐)
findByText是getByText的异步版本,会自动等待元素出现(默认超时1000ms):
import { expect, test, vi } from 'vitest'; import '@testing-library/jest-dom'; import { render, screen } from '@testing-library/svelte'; import Component from '../src/lib/Component.svelte'; // Mock fetch API,避免依赖外部服务 vi.mock('node-fetch', () => ({ default: vi.fn(() => Promise.resolve({ json: () => Promise.resolve({ name: 'FOO' }) })) })); test('should render updated name after onMount', async () => { render(Component); // 等待异步更新完成后查找元素 const heading = await screen.findByText('Hello FOO'); expect(heading).toBeInTheDocument(); });
方案二:使用waitFor
如果需要更精细的等待控制,可以用waitFor包裹断言:
// ... 其他导入和mock代码 test('should render updated name after onMount', async () => { render(Component); await waitFor(() => { expect(screen.getByText('Hello FOO')).toBeInTheDocument(); }); });
关键说明
- 必须将测试函数标记为
async,并使用await等待异步操作完成,否则测试会在onMount执行结束前就提前结束。 - Mock fetch是测试中的最佳实践:避免真实请求依赖外部API的可用性,保证测试的稳定性和运行速度。
内容的提问来源于stack exchange,提问作者Sandeep Chayapathi
相关产品推荐
相关产品推荐

