如何处理传奇测试中的错误?

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.

据我所知似乎有一些小问题,

  1. 在成功测试中,您在操作中使用了 onSuccessonError,但是 saga 实现需要 successerror 属性相反。

  2. 在错误测试中,您将令牌选择器定义为:

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()
},
  1. 另一个问题是 e.message === 401 条件。我相信错误消息将始终是一个字符串,因此即使您在测试中执行 throw new Error(401),它也会被转换为字符串。所以你应该修改你的传奇以期待一个字符串:
e.message === '401'

修复了 2 和 3 后,错误条件应该会过去,注销函数将被调用。