[英]How to test catch statement in async await Action
我有一个等待 API 函数的操作。 使用我的模拟 API 可以轻松测试 try 中的快乐路径。 但是,不确定测试和覆盖.catch
的最佳方法。
import {getRoles} from '../shared/services/api';
export const Actions = {
SET_ROLES: 'SET_ROLES'
};
export const fetchRoles = () => async dispatch => {
try {
const response = await getRoles();
const roles = response.data;
dispatch({
type: Actions.SET_ROLES,
roles
});
} catch (error) {
dispatch({
type: Actions.SET_ROLES,
roles: []
});
}
};
import {fetchRoles} from '../party-actions';
import rolesJson from '../../shared/services/__mocks__/roles.json';
jest.mock('../../shared/services/api');
describe('Roles Actions', () => {
it('should set roles when getRoles() res returns', async () => {
const mockDispatch = jest.fn();
await fetchRoles()(mockDispatch);
try {
expect(mockDispatch).toHaveBeenCalledWith({
type: 'SET_ROLES',
roles: rolesJson
});
} catch (e) {
// console.log('fetchRoles error: ', e)
}
});
// Here is the problem test, how do we intentionally cause
// getRoles() inside of fetchRoles() to throw an error?
it('should return empty roles if error', async () => {
const mockDispatch = jest.fn();
await fetchRoles('throwError')(mockDispatch);
expect(mockDispatch).toHaveBeenCalledWith({
type: 'SET_ROLES',
roles: []
});
});
});
import rolesJson from './roles.json';
export const getRoles = async test => {
let mockGetRoles;
if (test === 'throwError') {
// console.log('sad')
mockGetRoles = () => {
return Promise.reject({
roles: []
});
};
} else {
// console.log('happy')
mockGetRoles = () => {
return Promise.resolve({
roles: rolesJson
});
};
}
try {
const roles = mockGetRoles();
// console.log('api mocks roles', roles);
return roles;
} catch (err) {
return 'the error';
}
};
^ 以上您可以看到我尝试过的方法,它确实有效,但它要求我以适合测试的方式更改我的代码,而不是应用程序的实际逻辑。
例如,要通过此测试,我必须通过实际代码传入一个变量(请参阅x
):
export const fetchRoles = (x) => async dispatch => {
try {
const response = await getRoles(x);
const roles = response.data;
我们如何强制模拟中的getRoles
在我们的悲伤路径.catch
测试中抛出错误?
您可以在每个测试的基础上模拟getRoles
API:
// getRoles will be just jest.fn() stub
import {getRoles} from '../../shared/services/api';
import rolesJson from '../../shared/services/__mocks__/roles.json';
// without __mocks__/api.js it will mock each exported function as jest.fn();
jest.mock('../../shared/services/api');
it('sets something if loaded successfully', async ()=> {
getRoles.mockReturnValue(Promise.resolve(rolesJson));
dispatch(fetchRoles());
await Promise.resolve(); // so mocked API Promise could resolve
expect(someSelector(store)).toEqual(...);
});
it('sets something else on error', async () => {
getRoles.mockReturnValue(Promise.reject(someErrorObject));
dispatch(fetchRoles());
await Promise.resolve();
expect(someSelector(store)).toEqual(someErrornessState);
})
我还建议您在调用后专注于存储状态,而不是调度的操作列表。 为什么? 因为实际上我们并不关心在我们存储预期数据时按什么顺序分派了哪些操作,对吗?
但是可以肯定的是,您仍然可以对dispatch
调用进行断言。 要点:不要模拟__mocks__
automocks 中返回的结果,而是在对等基础上这样做。
我通过在模拟 api 文件中添加一个名为mockGetRolesError
的函数解决了测试并获得了.catch
的行覆盖:
感谢@skyboyer 提出在模拟文件上使用方法的想法。
import {getRoles} from '../shared/services/api';
export const Actions = {
SET_ROLES: 'SET_ROLES'
};
export const fetchRoles = () => async dispatch => {
try {
const response = await getRoles();
const roles = response.data;
// console.log('ACTION roles:', roles);
dispatch({
type: Actions.SET_ROLES,
roles
});
} catch (error) {
dispatch({
type: Actions.SET_ROLES,
roles: []
});
}
};
现在在对悲伤路径的测试中,我只需要调用mockGetRolesError
将mockGetRolesError
的 api 的内部状态设置为返回错误模式。
import {fetchRoles} from '../party-actions';
import rolesJson from '../../shared/services/__mocks__/roles.json';
import {mockGetRolesError} from '../../shared/services/api';
jest.mock('../../shared/services/api');
describe('Roles Actions', () => {
it('should set roles when getRoles() res returns', async () => {
const mockDispatch = jest.fn();
try {
await fetchRoles()(mockDispatch);
expect(mockDispatch).toHaveBeenCalledWith({
type: 'SET_ROLES',
roles: rolesJson
});
} catch (e) {
return e;
}
});
it('should return empty roles if error', async () => {
const mockDispatch = jest.fn();
mockGetRolesError();
await fetchRoles()(mockDispatch);
expect(mockDispatch).toHaveBeenCalledWith({
type: 'SET_ROLES',
roles: []
});
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.