如何让Jest等待React组件HTML更新完成后再执行快照测试
Jest React组件异步快照测试解决方案
前置准备
你当前只完成了API模块的mock,还需要给对应的接口方法配置模拟返回值,否则接口不会返回正常数据,组件会一直停留在加载状态,示例配置如下:
jest.mock("../../../utils/utils/APIWrapper", () => ({ // 替换为你组件实际调用的API方法名 getLocationSummary: jest.fn().mockResolvedValue({ // 填入和生产环境接口返回格式一致的模拟数据 id: 1, address: "北京市朝阳区", visitorCount: 120 // 其他组件需要用到的字段 }) }))
方案1:等待指定加载元素消失(更稳定)
这种方式通过判断加载屏对应的DOM特征是否消失来触发快照生成,不受其他异步逻辑干扰,推荐优先使用:
import { waitFor } from '@testing-library/react' import renderer from 'react-test-renderer' import { BrowserRouter } from 'react-router-dom' import LocationSummary from './你的组件路径' it('matches the snapshot after data loaded', async () => { const tree = renderer .create( <BrowserRouter> <LocationSummary {...locationSummaryProps} /> </BrowserRouter> ) // 等待加载屏消失,可根据你的加载屏实际特征调整判断逻辑 await waitFor(() => { const renderTree = tree.toJSON() // 示例1:判断加载屏的类名不存在 expect(renderTree).not.toContainEqual(expect.objectContaining({ props: expect.objectContaining({ className: 'loading-screen' }) })) // 示例2:判断不存在"加载中"文本 // expect(JSON.stringify(renderTree)).not.toContain('加载中') }) expect(tree.toJSON()).toMatchSnapshot() })
方案2:等待所有异步任务执行完成(更简便)
如果不想做元素判断,也可以直接等待所有异步微任务执行完毕,再生成快照:
import renderer from 'react-test-renderer' import { BrowserRouter } from 'react-router-dom' import LocationSummary from './你的组件路径' // 工具函数:清空所有异步微任务 const flushPromises = () => new Promise(resolve => setImmediate(resolve)) it('matches the snapshot after data loaded', async () => { const tree = renderer .create( <BrowserRouter> <LocationSummary {...locationSummaryProps} /> </BrowserRouter> ) // 等待所有接口请求、状态更新异步逻辑执行完成 await flushPromises() // 手动触发渲染树更新,同步最新的组件状态 tree.update( <BrowserRouter> <LocationSummary {...locationSummaryProps} /> </BrowserRouter> ) expect(tree.toJSON()).toMatchSnapshot() })
注意事项
- 测试用例必须声明为
async函数,否则await语法会报错 - 确保API mock的返回状态是
resolve,如果是reject状态,组件会走错误逻辑,不会渲染数据加载完成的内容 - 如果组件使用了React Suspense做数据请求或者懒加载,需要额外用
act包裹异步操作,避免状态更新警告
内容的提问来源于stack exchange,提问作者some
相关产品推荐
相关产品推荐

