React单元测试中如何在组件全部渲染完成后获取表格元素
问题根因
测试执行断言时,组件内useEffect触发的异步fetchUsers请求还没返回,users状态还是初始的空数组,此时表格内只有thead里的1个表头行,自然拿不到预期的193个tr。
另外当前测试没有Mock接口请求,直接走真实接口会导致测试不稳定、执行速度慢。
修复步骤
1. Mock接口请求
在测试文件中Mockapi模块的fetchUsers方法,返回固定的192条测试数据,避免真实发起网络请求:
jest.mock('api', () => ({ fetchUsers: jest.fn(() => Promise.resolve( Array.from({ length: 192 }, (_, idx) => ({ id: idx + 1, fullName: `TestUser${idx + 1}`, email: `test${idx + 1}@example.com` })) )) }))
2. 等待异步渲染完成后再断言
使用Testing Library提供的waitFor工具,等待异步状态更新、组件重渲染完成后再执行断言,修改测试代码如下:
import { render, waitFor } from '@testing-library/react' import React from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; import '@testing-library/jest-dom/extend-expect'; import UserTable from '../components/users/UserTable'; // 此处插入上面写的fetchUsers mock代码 test("Test #1: Count Users", async () => { const component = render( <Router> <UserTable /> </Router> ); await waitFor(() => { const tableContainer = component.getByTestId('userTest') expect(tableContainer.querySelectorAll('tr').length).toBe(193) }) })
写法优化
可以直接用findBy*系列查询方法,它是waitFor和getBy*的封装,写法更简洁:
test("Test #1: Count Users", async () => { const component = render( <Router> <UserTable /> </Router> ); const tableContainer = await component.findByTestId('userTest') await waitFor(() => { expect(tableContainer.querySelectorAll('tr').length).toBe(193) }) })
不要用固定延时
setTimeout的方式等待渲染,这种写法会拖慢测试速度,还可能因为运行环境性能差异导致偶发失败。
内容的提问来源于stack exchange,提问作者Gerald Hoxha
相关产品推荐
相关产品推荐

