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

求Expo React Native项目中含RTK Query Hooks组件的测试步骤

在Expo React Native中测试RTK Query Hooks组件的可行方案

因为MSW不支持React Native环境,直接使用会触发不兼容错误,这里提供两种实用的测试方案,覆盖不同测试场景:

方案一:直接Mock RTK Query生成的Hooks

这种方法无需配置Redux Store,专注测试组件的UI逻辑,适合快速验证不同状态下的组件表现。

步骤:

  1. 在测试文件中mock目标Hook,保留原API切片的其他导出(避免影响其他逻辑)
  2. 为不同测试用例设置Hook的返回值(加载中、成功、错误三种核心状态)
  3. 渲染组件并断言UI表现

示例代码:

import { render, screen } from '@testing-library/react-native';
import MyComponent from '../MyComponent';
import { useGetDataQuery } from '../apiSlice';

// Mock RTK Query的Hook,保留原模块的其他内容
jest.mock('../apiSlice', () => ({
  ...jest.requireActual('../apiSlice'),
  useGetDataQuery: jest.fn(),
}));

describe('MyComponent', () => {
  // 测试加载状态
  it('显示加载提示', () => {
    (useGetDataQuery as jest.Mock).mockReturnValue({
      data: undefined,
      error: undefined,
      isLoading: true,
    });

    render(<MyComponent />);
    expect(screen.getByText('加载中...')).toBeTruthy();
  });

  // 测试数据成功返回的场景
  it('渲染获取到的数据', () => {
    const mockData = { id: 1, name: '测试内容' };
    (useGetDataQuery as jest.Mock).mockReturnValue({
      data: mockData,
      error: undefined,
      isLoading: false,
    });

    render(<MyComponent />);
    expect(screen.getByText(mockData.name)).toBeTruthy();
  });

  // 测试错误状态
  it('显示错误提示', () => {
    (useGetDataQuery as jest.Mock).mockReturnValue({
      data: undefined,
      error: { status: 500, data: '服务器异常' },
      isLoading: false,
      isError: true,
    });

    render(<MyComponent />);
    expect(screen.getByText('加载失败:服务器异常')).toBeTruthy();
  });
});

方案二:配置Mock Redux Store测试完整数据流

这种方法更贴近真实运行环境,可以验证RTK Query的请求触发、状态流转逻辑,适合需要测试组件与Redux交互的场景。

步骤:

  1. 创建测试专用的Redux Store,包含RTK Query的Reducer和Middleware
  2. 通过Store的dispatch方法mock目标Endpoint的响应结果
  3. 用Provider包裹组件后渲染,断言异步状态下的UI变化

示例代码:

import { render, screen, waitFor } from '@testing-library/react-native';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import { apiSlice } from '../apiSlice';
import MyComponent from '../MyComponent';

describe('MyComponent', () => {
  let testStore;

  // 每个测试用例前初始化Store
  beforeEach(() => {
    testStore = configureStore({
      reducer: {
        [apiSlice.reducerPath]: apiSlice.reducer,
      },
      middleware: getDefaultMiddleware =>
        getDefaultMiddleware().concat(apiSlice.middleware),
    });
  });

  // 测试成功获取数据的完整流程
  it('加载完成后渲染数据', async () => {
    // Mock Endpoint的成功响应
    testStore.dispatch(apiSlice.endpoints.getData.initiate(null, {
      forceRefetch: true,
    })).unwrap.mockResolvedValue({ id: 1, name: '测试内容' });

    render(
      <Provider store={testStore}>
        <MyComponent />
      </Provider>
    );

    // 先断言加载状态
    expect(screen.getByText('加载中...')).toBeTruthy();
    // 等待异步数据返回后断言内容
    await waitFor(() => {
      expect(screen.getByText('测试内容')).toBeTruthy();
    });
  });

  // 测试错误处理流程
  it('请求失败时显示错误信息', async () => {
    // Mock Endpoint的失败响应
    testStore.dispatch(apiSlice.endpoints.getData.initiate(null, {
      forceRefetch: true,
    })).unwrap.mockRejectedValue({ status: 500, data: '服务器异常' });

    render(
      <Provider store={testStore}>
        <MyComponent />
      </Provider>
    );

    await waitFor(() => {
      expect(screen.getByText('加载失败:服务器异常')).toBeTruthy();
    });
  });
});

注意事项

  • 如果使用Expo的测试环境,确保已配置jest-expo作为测试预设(在jest.config.js中设置preset: 'jest-expo')
  • 若组件中有触发请求的交互(比如按钮点击),可以用fireEvent模拟操作,再断言状态变化
  • 方案一适合单元测试,方案二适合集成测试,可根据需求选择

内容的提问来源于stack exchange,提问作者renuka devi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:18:09