【问题标题】:How to test api call in Redux Saga properly as a unit?如何作为一个单元正确测试 Redux Saga 中的 api 调用?
【发布时间】:2022-02-22 11:11:52
【问题描述】:

我想测试这个 saga API 函数:

export function* fetchEshopProjects(action: ProjectActionsGetEshopProjects) {
    yield put(projectActions.currentEshopProjectsLoading(true))

    const response: {
        projects: string[],
        error: Error
    } = yield call(ajax.json, '/new-project/eshops-projects/?eshopId=' + action.eshopId)

    if (response.error) {
        yield put(projectActions.currentEshopProjectsFailed(response.error))
        yield put(projectActions.currentEshopProjectsLoading(false))
    } else {
        yield put(projectActions.setCurrentEshopProjects(response.projects))
        yield put(projectActions.currentEshopProjectsLoading(false))
    }
}

我已经写了这个测试:

test('fetch projects', async() => {
        mockParams({
            locale: 'en-US',
        });

        ajax.json = jest.fn().mockResolvedValue(['kbp', 'tbp'])
        const dispatched = []
        await runSaga({
            dispatch: (action) => dispatched.push(action),
        },
            fetchEshopProjects
        )
        expect(dispatched).toEqual([
            {
                type: 'CURRENT_ESHOP_PROJECTS_LOADING',
                loadingState: true,
            },
            {
                type: 'SET_CURRENT_ESHOP_PROJECTS',
                payload: ['kbp', 'tbp'],
            },
            {
                type: 'CURRENT_ESHOP_PROJECTS_LOADING',
                loadingState: false,
            },
        ])
    })

似乎代码只到达yield call(ajax.json... 部分,然后返回到测试功能——因此只记录了第一次调度。如何更正测试以使其成功结束?

【问题讨论】:

    标签: reactjs typescript react-redux jestjs redux-saga


    【解决方案1】:

    您忘记将task.toPromise 用于runSaga 返回的任务。下面是一个工作示例:

    saga.ts:

    import { call, put } from 'redux-saga/effects';
    import { ajax } from './ajax';
    
    export const projectActions = {
      currentEshopProjectsLoading(loadingState) {
        return { type: 'CURRENT_ESHOP_PROJECTS_LOADING', loadingState };
      },
      setCurrentEshopProjects(payload) {
        return { type: 'SET_CURRENT_ESHOP_PROJECTS', payload };
      },
      currentEshopProjectsFailed(error) {
        return { type: 'CURRENT_ESHOP_PROJECTS_FAILED', error };
      },
    };
    
    export function* fetchEshopProjects(action) {
      yield put(projectActions.currentEshopProjectsLoading(true));
    
      const response: {
        projects: string[];
        error: Error;
      } = yield call(ajax.json, '/new-project/eshops-projects/?eshopId=' + action.eshopId);
    
      if (response.error) {
        yield put(projectActions.currentEshopProjectsFailed(response.error));
        yield put(projectActions.currentEshopProjectsLoading(false));
      } else {
        yield put(projectActions.setCurrentEshopProjects(response.projects));
        yield put(projectActions.currentEshopProjectsLoading(false));
      }
    }
    

    ajax.ts:

    export const ajax = {
      async json(url) {},
    };
    

    saga.test.ts:

    import { runSaga } from 'redux-saga';
    import { ajax } from './ajax';
    import { fetchEshopProjects } from './saga';
    
    test('fetch projects', async () => {
      ajax.json = jest.fn().mockResolvedValue({ projects: ['kbp', 'tbp'] });
      const dispatched: any[] = [];
      await runSaga(
        {
          dispatch: (action) => dispatched.push(action),
        },
        fetchEshopProjects as any,
        { eshopId: '123' },
      ).toPromise();
      expect(dispatched).toEqual([
        {
          type: 'CURRENT_ESHOP_PROJECTS_LOADING',
          loadingState: true,
        },
        {
          type: 'SET_CURRENT_ESHOP_PROJECTS',
          payload: ['kbp', 'tbp'],
        },
        {
          type: 'CURRENT_ESHOP_PROJECTS_LOADING',
          loadingState: false,
        },
      ]);
    });
    

    测试结果:

     PASS   redux-saga-examples  packages/redux-saga-examples/src/stackoverflow/71176872/saga.test.ts
      ✓ fetch projects (6 ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   81.25 |       75 |      60 |   81.25 |                   
     ajax.ts  |     100 |      100 |       0 |     100 |                   
     saga.ts  |      80 |       75 |      75 |      80 | 12,25-26          
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        2.623 s, estimated 3 s
    

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多