异步 redux 动作测试总是 return 未决
Async redux actions tests always return pending
我正在为一些异步操作编写测试,但是测试失败了,因为返回的 type
总是 REQUEST_PENDING
。因此,即使对于获取数据时的测试,类型也不会改变并且测试失败。我不确定我做错了什么。
所以 REQUEST_SUCCESS
和 REQUEST_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_FAILED
或 REQUEST_SUCCESS
动作。
在您的第二个和第三个测试用例中,store.getActions()
数组实际上有两个元素:未决操作和结果操作。您需要 expect
操作是一个包含两者的数组。 REQUEST_FAILED
和 REQUEST_SUCCESS
操作在那里,但您看不到它们,因为它们是第二个元素。
将您的 pendingAction
定义为一个变量,因为您在所有三个测试中都需要它。
const pendingAction = {
type: REQUEST_PENDING
}
然后将其包含在您的 expectedActions
数组中。
const expectedActions = [
pendingAction,
{
type: REQUEST_SUCCESS,
payload: {
data: payload
}
}
]
这将使您的成功测试通过。我快速进行了 运行 测试,失败测试仍然失败,因为它没有正确模拟 API 失败。现在它返回成功,因为 requestRobots
函数使用真正的 axios 对象而不是模拟 axios 适配器。但也许您环境中的某些东西会以不同的方式处理此问题。
我正在为一些异步操作编写测试,但是测试失败了,因为返回的 type
总是 REQUEST_PENDING
。因此,即使对于获取数据时的测试,类型也不会改变并且测试失败。我不确定我做错了什么。
所以 REQUEST_SUCCESS
和 REQUEST_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_FAILED
或 REQUEST_SUCCESS
动作。
在您的第二个和第三个测试用例中,store.getActions()
数组实际上有两个元素:未决操作和结果操作。您需要 expect
操作是一个包含两者的数组。 REQUEST_FAILED
和 REQUEST_SUCCESS
操作在那里,但您看不到它们,因为它们是第二个元素。
将您的 pendingAction
定义为一个变量,因为您在所有三个测试中都需要它。
const pendingAction = {
type: REQUEST_PENDING
}
然后将其包含在您的 expectedActions
数组中。
const expectedActions = [
pendingAction,
{
type: REQUEST_SUCCESS,
payload: {
data: payload
}
}
]
这将使您的成功测试通过。我快速进行了 运行 测试,失败测试仍然失败,因为它没有正确模拟 API 失败。现在它返回成功,因为 requestRobots
函数使用真正的 axios 对象而不是模拟 axios 适配器。但也许您环境中的某些东西会以不同的方式处理此问题。