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

使用Jest测试Redux Saga的fetchStripeLocations方法遇问题求助

Redux Saga fetchStripeLocations方法Jest测试问题排查

我在使用Jest测试Redux Saga中的fetchStripeLocations方法时遇到问题,附上该Saga方法代码、测试用例及控制台截图,希望帮忙排查问题。已多次谷歌搜索但未找到解决方案,盼协助。


Saga方法代码

export function* fetchStripeLocations() {
    console.log('saga fetchStripeLocations called:');
    try {
        const BE = yield select((state) => state.BE);
        const PaymentRequestFormReducer = yield select(state => state.PaymentRequestFormReducer.toJS());
        const { stripeLocationsMap } = PaymentRequestFormReducer;
        const paymentsEnabled = isPaymentsEnabled(BE);

        if (!stripeLocationsMap.data && !stripeLocationsMap.isLoading && paymentsEnabled) {
            yield put(actionCreator.fetchingStripeLocations());
            const url = actionCreator.URL.FETCH_STRIPE_LOCATIONS;
            const response = yield call(beAPIResource.get, url, {}, { topLoader: false, isPrimaryAPI: false, cancellable: false });
            const { qcrEnabled, stripeLocationsMap } = response.data;
            yield put(actionCreator.setStripeLocations({ qcrEnabled, stripeLocationsMap }));
        }
    } catch (e) {
        yield put(actionCreator.setStripeLocations({ stripeLocationsMap: {} }));
        yield put(dataFetchingError(e, "Something went wrong please try again later"));
    }
}

测试用例代码

import { testData } from "./TestReducerData";
import { commonTestData } from "../../../../../../__test__/commonTestData";

test('fetchStripeLocations testing should pass', async () => {
    const dispatchedActions = [];
    const stripeDummyData = iMap({
        isLoading: false,
        data: null,
        qcrEnabled: false
    });

    const mockData = { 
        qcrEnabled : false, 
        stripeLocationsMap: {
            isLoading: false,
            data: null,
            qcrEnabled: false
        }
    };

    const mRequest = jest.fn(() => Promise.resolve(mockData));
    const mockState = {
        BE: commonTestData,
        PaymentRequestFormReducer: testData.initialState
    };
    await runSaga({
            dispatch: (action) => dispatchedActions.push(action),
            getState: () => mockState,
        }, PaymentRequestFormSaga.fetchStripeLocations).done;
    console.log('dispatchedActions', dispatchedActions);
    console.log('mRequest.mock:', mRequest.mock);
    expect(mRequest.mock.calls.length).toBe(1);

    expect(dispatchedActions).toEqual([ActionCreator.setStripeLocations(mockData)]);
});

控制台截图

控制台截图1
控制台截图2


问题排查及解决方案

  1. API调用未被模拟
    测试代码中定义了mRequest但并未替换Saga中实际使用的beAPIResource.get,导致真实API被调用而非模拟方法,因此mRequest.mock.calls.length始终为0。
    解决:在测试前模拟API方法:

    jest.mock('path/to/beAPIResource', () => ({
      get: jest.fn(() => Promise.resolve({ data: mockData }))
    }));
    
  2. 状态判断条件未满足
    Saga中需同时满足!stripeLocationsMap.data && !stripeLocationsMap.isLoading && paymentsEnabled才会执行后续逻辑,需确认:

    • testData.initialState.toJS()返回的stripeLocationsMap是否符合data: null且isLoading: false
    • isPaymentsEnabled(commonTestData)是否返回true
      解决:手动设置mock状态确保条件成立:
    const mockState = {
      BE: commonTestData,
      PaymentRequestFormReducer: iMap({
        stripeLocationsMap: {
          data: null,
          isLoading: false
        }
      })
    };
    
  3. dispatch断言错误
    Saga中会先dispatchactionCreator.fetchingStripeLocations(),再dispatchsetStripeLocations,测试预期只包含一个action不符合实际逻辑。
    解决:修改断言为:

    expect(dispatchedActions).toEqual([
      actionCreator.fetchingStripeLocations(),
      actionCreator.setStripeLocations(mockData)
    ]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:35:17