如何处理传奇测试中的错误?
How to handle errors in saga testing?
我正在尝试测试以下 saga,但它一直失败,我认为我的主要问题是模拟结果、错误消息和竞赛效果中的令牌状态。
传奇
export function* handleFetchUser(action) {
const token = yield select(getToken);
try{
const { result } = yield race({
result: call(fetchUser, url),
timeout: delay(1000),
});
if(result){
yield call(action.success, result, action);
}
}
catch(e){
if(e.message === 401 && token.status === 'logout'){
yield call(logoutUser, action);
}else if(e.message === 500 && token.status){
yield call(action.error);
}
}
}
测试成功:
it('should fetch users', () => {
const action = {
type: "Get Users",
onSuccess: jest.fn(),
onError: jest.fn(),
};
return expectSaga(handleFetch, action)
.provide({
select: tokenSelector,
race: () => ({ result: mockResponse }),
})
.call(action.onSuccess, mockResponse, action)
.dispatch(action)
.not.call(action.onError)
.run();
});
测试错误:
it('should request logout user on error 401', () => {
const action = {
type: 'Get User data',
};
return expectSaga(handleFetchUser, action)
.provide({
race: () => {
throw new Error(401);
},
select: ({ selector }, next) => {
if (selector === getToken) {
return undefined;
}
return next();
},
call: ({ fn }, next) => {
if (fn === logoutUser) {
return jest.fn();
}
return next();
},
})
.select(getToken)
.call(logoutUser, action)
.dispatch(action)
.run();
})
为了成功,它无法从比赛中获得result/response。
对于错误,有一次,我去掉了catch中的if else部分,没问题,logoutUser call pass.
据我所知似乎有一些小问题,
在成功测试中,您在操作中使用了 onSuccess
和 onError
,但是 saga 实现需要 success
和 error
属性相反。
在错误测试中,您将令牌选择器定义为:
select: ({ selector }, next) => {
if (selector === getToken) {
return undefined;
}
return next();
}
这意味着 getToken 函数将 return 未定义,因此 token.status === 'logout'
不会通过。所以你可能想要这个:
select: ({selector}, next) => {
if (selector === getToken) {
return {
status: 'logout',
}
}
return next()
},
- 另一个问题是
e.message === 401
条件。我相信错误消息将始终是一个字符串,因此即使您在测试中执行 throw new Error(401)
,它也会被转换为字符串。所以你应该修改你的传奇以期待一个字符串:
e.message === '401'
修复了 2 和 3 后,错误条件应该会过去,注销函数将被调用。
我正在尝试测试以下 saga,但它一直失败,我认为我的主要问题是模拟结果、错误消息和竞赛效果中的令牌状态。
传奇
export function* handleFetchUser(action) {
const token = yield select(getToken);
try{
const { result } = yield race({
result: call(fetchUser, url),
timeout: delay(1000),
});
if(result){
yield call(action.success, result, action);
}
}
catch(e){
if(e.message === 401 && token.status === 'logout'){
yield call(logoutUser, action);
}else if(e.message === 500 && token.status){
yield call(action.error);
}
}
}
测试成功:
it('should fetch users', () => {
const action = {
type: "Get Users",
onSuccess: jest.fn(),
onError: jest.fn(),
};
return expectSaga(handleFetch, action)
.provide({
select: tokenSelector,
race: () => ({ result: mockResponse }),
})
.call(action.onSuccess, mockResponse, action)
.dispatch(action)
.not.call(action.onError)
.run();
});
测试错误:
it('should request logout user on error 401', () => {
const action = {
type: 'Get User data',
};
return expectSaga(handleFetchUser, action)
.provide({
race: () => {
throw new Error(401);
},
select: ({ selector }, next) => {
if (selector === getToken) {
return undefined;
}
return next();
},
call: ({ fn }, next) => {
if (fn === logoutUser) {
return jest.fn();
}
return next();
},
})
.select(getToken)
.call(logoutUser, action)
.dispatch(action)
.run();
})
为了成功,它无法从比赛中获得result/response。 对于错误,有一次,我去掉了catch中的if else部分,没问题,logoutUser call pass.
据我所知似乎有一些小问题,
在成功测试中,您在操作中使用了
onSuccess
和onError
,但是 saga 实现需要success
和error
属性相反。在错误测试中,您将令牌选择器定义为:
select: ({ selector }, next) => {
if (selector === getToken) {
return undefined;
}
return next();
}
这意味着 getToken 函数将 return 未定义,因此 token.status === 'logout'
不会通过。所以你可能想要这个:
select: ({selector}, next) => {
if (selector === getToken) {
return {
status: 'logout',
}
}
return next()
},
- 另一个问题是
e.message === 401
条件。我相信错误消息将始终是一个字符串,因此即使您在测试中执行throw new Error(401)
,它也会被转换为字符串。所以你应该修改你的传奇以期待一个字符串:
e.message === '401'
修复了 2 和 3 后,错误条件应该会过去,注销函数将被调用。