React-admin列表页单元测试无法读取Mock数据问题求助
React Admin List组件单元测试问题排查与解决
问题场景
对基于List的React Admin组件做单元测试,已在AdminContext中配置仅包含getList()方法的mock dataProvider(该方法已被调用),但测试失败且出现act警告。
组件代码
const BookList = (props:any) => { return ( <List {...props}> <Datagrid> <TextField source='title'/> </Datagrid> </List> ) }
测试代码
describe('list test', () => { it('list test', async () => { let dataProvider:DataProvider = testDataProvider({ getList: function <RecordType extends RaRecord<Identifier> = any>(resource: string, params: GetListParams): Promise<GetListResult<RecordType>> { let record:RecordType = { id:"1", title:'myTitle' }as unknown as RecordType; return Promise.resolve({data:[record],total:1}); } }); render( <AdminContext dataProvider={dataProvider}> <BookList resource='books'/> </AdminContext> ); expect(await screen.getByText('myTitle')).toBeInTheDocument(); }); })
问题表现
- 测试失败:DOM中列表行数为0,无法找到
myTitle文本 - 控制台出现act警告:
Warning: An update to ListBase inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state /
});
/ assert on the output */
解决方法
1. 用waitFor替代直接await断言
React Admin的List组件内部会异步请求数据并更新状态,await screen.getByText()无法正确等待所有渲染完成。改用waitFor包裹断言,它会自动处理act的状态更新包裹:
// 替换原断言代码 await waitFor(() => { expect(screen.getByText('myTitle')).toBeInTheDocument(); });
2. 补充AdminContext必要配置
List组件依赖i18nProvider上下文,即使使用默认实现也需要显式传入,否则可能导致渲染异常:
import { defaultI18nProvider } from 'react-admin'; // 修改render部分 render( <AdminContext dataProvider={dataProvider} i18nProvider={defaultI18nProvider} > <BookList resource='books'/> </AdminContext> );
3. 确保mock dataProvider返回格式正确
给mock的getList添加日志,确认是否被正确调用,同时保证返回数据结构完全符合React Admin的要求:
getList: function <RecordType extends RaRecord<Identifier> = any>(resource: string, params: GetListParams): Promise<GetListResult<RecordType>> { console.log('getList triggered for resource:', resource); // 验证调用情况 const record: RecordType = { id: "1", title: 'myTitle' } as unknown as RecordType; return Promise.resolve({ data: [record], total: 1 }); }
4. 强制List显示所有数据
避免分页逻辑导致数据不显示,给List组件添加perPage参数:
const BookList = (props:any) => { return ( <List {...props} perPage={100}> <Datagrid> <TextField source='title'/> </Datagrid> </List> ) }
内容的提问来源于stack exchange,提问作者MikaelW
相关产品推荐
相关产品推荐

