SolidJS使用Vitest测试createResource错误状态时触发未处理错误
问题现象
测试SolidJS组件时出现如下问题:组件在API返回404状态码时会渲染“Track not found”提示,正常运行时逻辑完全符合预期,但执行Vitest测试时会抛出错误:
Vitest caught 1 unhandled error during the test run. This might cause false positive tests.
涉及代码
Similar.tsx 组件代码
const Tracks: Component<Params> = (props) => { return ( <Show when={!tracks.error} fallback={<ErrorMessage message="Track not found" />} > <div class="tracks"> <For each={tracks()} fallback={<ErrorMessage message="No similar tracks found" />} > {(track) => ( <Track name={track.name} artist={track.artist.name} image={track.image[3]['#text']} url={track.url} /> )} </For> </div> </Show> ); };
测试用例代码
it('renders a "Track not found" message if API returns 404', async () => { vitest .spyOn(fetchSimilarTracks, 'default') .mockRejectedValueOnce(new Error('Track not found')); const { findByText } = renderSimilar({ track: 'hdsauidhas', artist: 'hdsduhsd', }); expect(await findByText('Track not found')).toBeInTheDocument(); });
问题原因
这个报错的核心是mock接口返回的rejected Promise没有被测试流程完整捕获:
你用mockRejectedValueOnce模拟接口报错后,Solid的createResource(即代码中用到的tracks响应式资源)会接收这个错误,更新tracks.error状态触发fallback渲染,整个UI逻辑是正确的。但这个rejected状态的Promise本身没有被任何await或者catch逻辑捕获,最终冒泡到Vitest的全局进程,触发了未处理错误告警。findByText只会轮询等待目标文本出现在DOM中,不会等待组件内所有异步Promise都被处理完成,所以哪怕DOM断言通过,未捕获的Promise拒绝依然会触发Vitest的报错。
修复方案
- 优先方案:主动捕获资源的rejected状态。如果
renderSimilar工具函数能暴露内部创建的tracks资源引用,在findByText断言后补充await expect(tracks).rejects.toThrow('Track not found')即可,主动处理这个抛出的Promise,避免它变成全局未捕获错误。 - 更贴合真实运行逻辑的方案:渲染测试组件时包裹一层和生产环境一致的错误边界组件,接住资源加载过程中抛出的错误,让错误处理流程和线上完全一致,从根源上避免错误冒泡到测试全局。
- 临时兜底方案:如果确认组件错误处理逻辑完全正确,也可以在当前测试用例内临时重写未捕获reject的处理逻辑,但这种方式治标不治本,不推荐优先使用。
内容的提问来源于stack exchange,提问作者Henrique Ramos
相关产品推荐
相关产品推荐

