如何用React Testing Library测试基于Redux Toolkit Query的React组件
Redux Toolkit Query组件的React Testing Library单元测试方案
我用Redux Toolkit Query在React组件中发起API请求,功能运行完全正常,但在使用React Testing Library为该组件编写单元测试用例时遇到了困难。相关代码实现如下:
RTK Query API定义
const AssetInstancesAPI = createApi({ baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:3003', headers: genHeaders(token) }), reducerPath: 'AssetInstances', tagTypes: [`table-contents`], endpoints: (build) => ({ getAssetsTableData: build.query<any, void>({ query: (body) => ({ url: '/assets/summary', method: 'get', data: body }), providesTags: [`table-contents`] }) }) }); export const { useGetAssetsTableDataQuery } = AssetInstancesAPI;
使用RTK Query的React组件
const AssetInstancesTabularView = () => { const { data, isLoading } = useGetAssetsTableDataQuery(null); return ( <StyledDataTable data-testid='asset-instance-tabular-view'> <DataTable title='' selectionMode='multiple' loading={isLoading} data={data?.contents || []} reorderableColumns={true} resizableColumns={true}> {!isLoading && data?.columns?.map((column) => <DataTable.Column key={column.field} field={column.field} header={column.header} sortable={true} />)} </DataTable> </StyledDataTable> ); };
测试方案及代码示例
1. 配置测试专用Store
首先需要创建包含RTK Query reducer的测试Store,避免发起真实API请求:
import { render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { configureStore } from '@reduxjs/toolkit'; import AssetInstancesAPI from './path-to-your-api-file'; import AssetInstancesTabularView from './path-to-your-component'; // 创建测试用Store const createTestStore = () => configureStore({ reducer: { [AssetInstancesAPI.reducerPath]: AssetInstancesAPI.reducer, }, middleware: getDefaultMiddleware => getDefaultMiddleware().concat(AssetInstancesAPI.middleware), }); // 模拟API返回的测试数据 const mockSuccessData = { contents: [ { id: 1, name: '测试资产1', category: '设备' }, { id: 2, name: '测试资产2', category: '工具' }, ], columns: [ { field: 'id', header: '资产ID' }, { field: 'name', header: '资产名称' }, { field: 'category', header: '资产类别' }, ], };
2. 测试加载状态
验证组件在API请求过程中是否显示加载状态:
test('组件加载时显示加载状态', async () => { const store = createTestStore(); render( <Provider store={store}> <AssetInstancesTabularView /> </Provider> ); // 通过测试ID定位组件,检查DataTable的loading属性 const tableContainer = screen.getByTestId('asset-instance-tabular-view'); const dataTable = tableContainer.querySelector('[loading="true"]'); expect(dataTable).toBeInTheDocument(); });
3. 测试数据成功加载后的渲染
Mock API的成功响应,验证表格列和数据是否正确渲染:
test('成功获取数据后渲染完整表格', async () => { const store = createTestStore(); // Mock RTK Query的hook返回值 jest.spyOn(AssetInstancesAPI.endpoints.getAssetsTableData, 'useQuery') .mockReturnValue({ data: mockSuccessData, isLoading: false, isSuccess: true, error: null, }); render( <Provider store={store}> <AssetInstancesTabularView /> </Provider> ); // 等待异步数据渲染完成 await screen.findByText('资产ID'); // 验证表格列是否存在 expect(screen.getByText('资产ID')).toBeInTheDocument(); expect(screen.getByText('资产名称')).toBeInTheDocument(); expect(screen.getByText('资产类别')).toBeInTheDocument(); // 验证表格内容是否渲染 expect(screen.getByText('测试资产1')).toBeInTheDocument(); expect(screen.getByText('测试资产2')).toBeInTheDocument(); });
4. 测试空数据场景
Mock空数据响应,验证组件的空状态渲染:
test('数据为空时渲染空表格', async () => { const store = createTestStore(); jest.spyOn(AssetInstancesAPI.endpoints.getAssetsTableData, 'useQuery') .mockReturnValue({ data: { contents: [], columns: [] }, isLoading: false, isSuccess: true, }); render( <Provider store={store}> <AssetInstancesTabularView /> </Provider> ); await screen.findByTestId('asset-instance-tabular-view'); // 检查是否没有表格列 const columnHeaders = screen.queryAllByRole('columnheader'); expect(columnHeaders.length).toBe(0); });
注意事项
- 测试重点放在组件的UI表现,无需测试RTK Query内部逻辑
- 处理异步状态时,使用React Testing Library的
findBy*系列方法配合await - 如果
genHeaders依赖全局token,测试时需要mock该函数返回测试用的headers
内容的提问来源于stack exchange,提问作者Abhin Pai
相关产品推荐
相关产品推荐

