javascript - 如何在异步等待操作中测试 catch 语句
问题描述
问题
我有一个等待 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: []
});
});
});
模拟 API
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__
而是在对等基础上进行。
推荐阅读
- javascript - 在 Bootstrap 4 表单中通过 AJAX 进行 PHP POST 的问题
- rdf - RDF知识图谱中的无效字符等问题
- javascript - 在函数中获取变量并将其分配给超出其范围的另一个变量
- python-3.x - 如何将输入字符串转换为pyspark中列的每一行的字典
- mysql - 在时间表上表示事件发生
- azure - 使用托管标识对 Azure 服务总线进行经过身份验证的 REST API 调用
- spring - 在带有 Postgres 的 Spring Boot 中使用 mybatis 批量插入 UUID 错误
- javascript - 将上传文件转换为字节数组以发送到 Angular/Typescript 中的 API 请求
- php - Laravel HasManyThrough 同一个模型,作用域不同
- html - 我们可以在单个 ul 中使用多个 ul 元素而不是多个 li 元素吗?