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

React Native中redux-saga单元测试的正确写法与示例咨询

Redux Saga 单元测试实现方案

前置准备

首先需要调整你的 saga 文件,将内部的 getUsers、getProfiles 函数也导出,方便单独测试:

// 原有代码不变,新增导出
export function* getUsers(action) { /* 原有逻辑 */ }
export function* getProfiles(action) { /* 原有逻辑 */ }
export function* usersSaga() { /* 原有逻辑 */ }

需要覆盖的测试逻辑点

  • 根saga usersSaga 正确绑定了对应 action 类型和处理函数
  • 接口请求成功场景:正确调用对应 API、分发加载成功的 action
  • 接口请求失败场景:正确执行错误处理逻辑、分发加载失败的 action

基础实现示例

以下提供两种实现方式,第一种为无额外依赖的原生 Generator 迭代写法,第二种为常用的 redux-saga-test-plan 简化写法。

方式1:原生 Generator 迭代测试(无需额外依赖)

import { call, put, takeLatest } from 'redux-saga/effects';
import { usersSaga, getUsers } from '../sagas/users/';
import api from '你的api文件路径';
import userConstants from '你的常量文件路径';
import errorHandler from '你的错误处理文件路径';

describe('Users Saga', () => {
  // 测试根saga监听逻辑
  it('根saga正确监听对应action', () => {
    const gen = usersSaga();
    // 断言第一个yield是监听GET_USERS
    expect(gen.next().value).toEqual(takeLatest(userConstants.GET_USERS, getUsers));
    // 断言第二个yield是监听GET_USER_PROFILES
    expect(gen.next().value).toEqual(takeLatest(userConstants.GET_USER_PROFILES, getProfiles));
    // 断言执行结束
    expect(gen.next().done).toBe(true);
  });

  // 测试getUsers正常请求流程
  it('getUsers正常请求时正确调用api并分发成功action', () => {
    const mockAction = { payload: { id: 123 } };
    const mockResData = [{ id: 1, name: '测试用户' }];
    const gen = getUsers(mockAction);

    // 第一步:调用getUsers接口
    expect(gen.next().value).toEqual(call(api.users.getUsers, { id: 123 }));
    // 第二步:传入接口返回值,断言分发成功action
    expect(gen.next({ data: mockResData }).value).toEqual(put({
      type: userConstants.LOAD_USERS,
      payload: mockResData
    }));
    // 断言执行结束
    expect(gen.next().done).toBe(true);
  });

  // 测试getUsers异常请求流程
  it('getUsers请求失败时正确执行错误处理并分发失败action', () => {
    const mockAction = { payload: { id: 123 } };
    const mockError = new Error('接口请求失败');
    const gen = getUsers(mockAction);

    // 第一步:调用接口
    gen.next();
    // 抛出错误,断言调用错误处理函数
    expect(gen.throw(mockError).value).toEqual(call(errorHandler, mockError));
    // 断言分发失败action
    expect(gen.next().value).toEqual(put({ type: userConstants.LOAD_USERS_FAIL }));
    // 断言执行结束
    expect(gen.next().done).toBe(true);
  });
})

方式2:使用redux-saga-test-plan简化测试

首先安装依赖:

npm install redux-saga-test-plan --save-dev

测试代码示例:

import { expectSaga } from 'redux-saga-test-plan';
import { call } from 'redux-saga/effects';
import { getUsers } from '../sagas/users/';
import api from '你的api文件路径';
import userConstants from '你的常量文件路径';
import errorHandler from '你的错误处理文件路径';

describe('Users Saga', () => {
  it('getUsers正常请求流程测试', () => {
    const mockAction = { payload: { id: 123 } };
    const mockResData = [{ id: 1, name: '测试用户' }];
    return expectSaga(getUsers, mockAction)
      // mock接口返回值
      .provide([
        [call(api.users.getUsers, { id: 123 }), { data: mockResData }]
      ])
      // 断言分发了成功的action
      .put({ type: userConstants.LOAD_USERS, payload: mockResData })
      .run();
  });

  it('getUsers异常请求流程测试', () => {
    const mockAction = { payload: { id: 123 } };
    const mockError = new Error('接口请求失败');
    return expectSaga(getUsers, mockAction)
      // mock接口抛出错误
      .provide([
        [call(api.users.getUsers, { id: 123 }), Promise.reject(mockError)]
      ])
      // 断言调用了错误处理函数
      .call(errorHandler, mockError)
      // 断言分发了失败的action
      .put({ type: userConstants.LOAD_USERS_FAIL })
      .run();
  });
})

getProfiles的测试逻辑和getUsers完全一致,替换对应的接口、常量即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 14:09:02