测试Async Redux Action Jest

测试Async Redux Action Jest

问题描述:

我无法从异步redux操作中获取正确的输出。我使用Jest,redux-mock-adapter和thunk作为工具。

I'm having trouble getting the correct output from an async redux action. I am using Jest, redux-mock-adapter, and thunk as the tools.

根据redux关于测试异步thunks的文档( https://redux.js.org/docs/recipes/WritingTests.html#async-action-creators ),我的测试应该返回两个动作的数组。但是,我的测试只返回第一个操作,而不是第二个应该返回成功获取的操作。我想我在这里只是遗漏了一些东西,但至少可以说是很麻烦。

According to redux's documentation on testing async thunks (https://redux.js.org/docs/recipes/WritingTests.html#async-action-creators), my tests should be returning an array of two actions. However, my test is only returning the first action, and not the second one that should return on a successful fetch. I think I'm just missing something small here, but it has been bothersome to say the least.

Redux Action

export const getRemoveFileMetrics = cacheKey => dispatch => {
    dispatch({ type: IS_FETCHING_DELETE_METRICS });
    return axios
        .get("GetRemoveFileMetrics", { params: { cacheKey } })
        .then(response => dispatch({ type: GET_REMOVE_FILE_METRICS, payload: response.data }))
        .catch(err => err);
};

测试

it("getRemoveFileMetrics() should dispatch GET_REMOVE_FILE_METRICS on successful fetch", () => {
        const store = mockStore({});
        const cacheKey = "abc123doremi";
        const removeFileMetrics = {
            cacheKey,
            duplicateFileCount: 3,
            uniqueFileCount: 12,
        };
        const expectedActions = [
            {
                type: MOA.IS_FETCHING_DELETE_METRICS,
            },
            {
                type: MOA.GET_REMOVE_FILE_METRICS,
                payload: removeFileMetrics,
            }
        ];
        mockRequest.onGet(`/GetRemoveFileMetrics?cacheKey=${cacheKey}`).reply(200, removeFileMetrics);
        return store.dispatch(MOA.getRemoveFileMetrics(cacheKey)).then(() => {
            const returnedActions = store.getActions();
            expect(returnedActions).toEqual(expectedActions);
        });
    });

输出

Expected value to equal:
    [{ "type": "IS_FETCHING_DELETE_METRICS" }, { "payload": { "cacheKey": "abc123doremi", "duplicateFileCount": 3, "uniqueFileCount": 12 }, "type": "GET_REMOVE_FILE_METRICS" }]
Received:
    [{ "type": "IS_FETCHING_DELETE_METRICS" }]


我正在使用 jest-fetch-mock 和没有 axios 。以下是我的行动。你可以重构 async await 作为第一步。对我来说,它只是这样工作。

I am using jest-fetch-mock and no axios. The following is working for me with the actions. You could refactor to async await as first step. For me it only worked that way.

我现在正在试图弄清楚如何测试副作用( showErrorAlert(jsonResponse); )。如果我在测试文件的顶部模拟出 showErrorAlert 实现(在我的例子中注释掉),那么我就会像你一样得到同样的问题。由于某种原因,不会触发使用fetch的操作。

I am now trying to figure out how to test the side effect (showErrorAlert(jsonResponse);). If I mock out the showErrorAlert implementation at the top of the test file (commented out in my example) then I get the same problem just like you. Actions that uses fetch won't get triggered for some reason.

export const submitTeammateInvitation = (data) => {
  const config = {
    //.....
  };

  return async (dispatch) => {
    dispatch(submitTeammateInvitationRequest());

    try {
      const response = await fetch(inviteTeammateEndpoint, config);
      const jsonResponse = await response.json();

      if (!response.ok) {
        showErrorAlert(jsonResponse);
        dispatch(submitTeammateInvitationError(jsonResponse));

        throw new Error(response.statusText);
      }

      dispatch(submitTeammateInvitationSuccess());
    } catch (error) {
      if (process.env.NODE_ENV === 'development') {
        console.log('Request failed', error);
      }
    }
  };
};

test

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

// jest.mock('../../../../_helpers/alerts', ()=> ({ showAlertError: jest.fn() }));

const middlewares = [thunk];
const createMockStore = configureMockStore(middlewares);

......

it('dispatches the correct actions on a failed fetch request', () => {
  fetch.mockResponse(
    JSON.stringify(error),
    { status: 500, statusText: 'Internal Server Error' }
  );

  const store = createMockStore({});
  const expectedActions = [
    {
      type: 'SUBMIT_TEAMMATE_INVITATION_REQUEST',
    },
    {
      type: 'SUBMIT_TEAMMATE_INVITATION_FAILURE',
      payload: { error }
    }
  ];

  return store.dispatch(submitTeammateInvitation(data))
    .then(() => {
      // expect(alerts.showAlertError).toBeCalled();
      expect(store.getActions()).toEqual(expectedActions);
    });
});