You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:10:15