异步 redux 动作测试总是 return 未决

Async redux actions tests always return pending

我正在为一些异步操作编写测试,但是测试失败了,因为返回的 type 总是 REQUEST_PENDING。因此,即使对于获取数据时的测试,类型也不会改变并且测试失败。我不确定我做错了什么。

所以 REQUEST_SUCCESSREQUEST_FAILED 是总是返回的测试 REQUEST_PENDING

这是我的actions.js

import axios from 'axios';
import {
  REQUEST_PENDING,
  REQUEST_SUCCESS,
  REQUEST_FAILED,
} from './constants';

export const setSearchField = (payload) => ({ type: SEARCH_EVENT, payload });

export const requestRobots = () => {
  return async (dispatch) => {
    dispatch({
      type: REQUEST_PENDING,
    });
    try {
      const result = await axios.get('//jsonplaceholder.typicode.com/users');
      dispatch({ type: REQUEST_SUCCESS, payload: result.data });
    } catch (error) {
      dispatch({ type: REQUEST_FAILED, payload: error });
    }
  };
};

这是我的actions.test.js

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import {
  REQUEST_PENDING,
  REQUEST_SUCCESS,
  REQUEST_FAILED,
} from './constants';
import * as actions from './actions';

const mock = new MockAdapter(axios);
const mockStore = configureMockStore([thunk]);
const payload = [
  {
    id: 1,
    name: 'robocop',
    email: 'robocop@gmail.com',
    key: 1,
  },
];


describe('handles requestRobots', () => {
  beforeEach(() => {
    // Runs before each test in the suite
    store.clearActions();
  });

  const store = mockStore();
  store.dispatch(actions.requestRobots());
  const action = store.getActions();

  it('Should return REQUEST_PENDING action', () => {
    expect(action[0]).toEqual({
      type: REQUEST_PENDING,
    });
  });


  it('Should return REQUEST_SUCCESS action', () => {
    mock.onGet('//jsonplaceholder.typicode.com/users').reply(200, {
      data: payload,
    });


    return store.dispatch(actions.requestRobots()).then(() => {
      const expectedActions = [
        {
          type: REQUEST_SUCCESS,
          payload: {
            data: payload,
          },
        },
      ];
      expect(store.getActions()).toEqual(expectedActions);
    });
  });

  it('Should return REQUEST_FAILURE action', () => {
    mock.onGet('//jsonplaceholder.typicod.com/users').reply(400, {
      data: payload,
    });


    return store.dispatch(actions.requestRobots()).then(() => {
      const expectedActions = [
        {
          type: REQUEST_FAILED,
          payload: {
            data: ['Error: Request failed with status code 404'],
          },
        },
      ];
      expect(store.getActions()).toEqual(expectedActions);
    });
  });
});

thunk 动作的生命周期是它会在每次调用开始时调度 REQUEST_PENDING 动作,然后在结束时调度 REQUEST_FAILEDREQUEST_SUCCESS 动作。

在您的第二个和第三个测试用例中,store.getActions() 数组实际上有两个元素:未决操作和结果操作。您需要 expect 操作是一个包含两者的数组。 REQUEST_FAILEDREQUEST_SUCCESS 操作在那里,但您看不到它们,因为它们是第二个元素。

将您的 pendingAction 定义为一个变量,因为您在所有三个测试中都需要它。

const pendingAction = {
  type: REQUEST_PENDING
}

然后将其包含在您的 expectedActions 数组中。

const expectedActions = [
  pendingAction,
    {
      type: REQUEST_SUCCESS,
      payload: {
        data: payload
      }
    }
]

这将使您的成功测试通过。我快速进行了 运行 测试,失败测试仍然失败,因为它没有正确模拟 API 失败。现在它返回成功,因为 requestRobots 函数使用真正的 axios 对象而不是模拟 axios 适配器。但也许您环境中的某些东西会以不同的方式处理此问题。