测试复杂的异步Redux操作

时间:2016-10-22 14:47:14

标签: javascript unit-testing asynchronous redux redux-thunk

所以,让我们说我有下一步行动:

export function login({ email, password, redirectTo, doNotRedirect }) {
  return ({ dispatch }) => {
    const getPromise = async () => {
      const basicToken = Base64.encode(`${email}:${password}`);
      const authHeaders = { Authorization: `Basic ${basicToken}` };
      const { payload, error } = await dispatch(sendAuthentication(authHeaders));

      if (error) throw payload;

      const { username, token, fromTemporaryPassword } = payload;
      const encodedToken = Base64.encode(`${username}:${token}`);

      dispatch(persistence.set('authorizationToken', encodedToken));
      dispatch(postGlobalId({ username }));
      dispatch(setIsLoggedIn(true));
      dispatch(setIsFromTemporaryPassword(fromTemporaryPassword));

      await dispatch(clientActions.fetchClient);

      if (doNotRedirect) return;

      if (fromTemporaryPassword)
        dispatch(updatePath('/profile/change-password'));
      else
        dispatch(updatePath(redirectTo || '/dashboard'));
    };

    return {
      type: AUTHENTICATION_LOGIN,
      payload: getPromise()
    };
  };
}

我想为它添加测试,以增加代码的可靠性。

所以,这里有一些事情:

  1. 我们发送身份验证标头并将数据作为回复
  2. 如果响应中存在某些错误,我们会抛出错误
  3. 我们设置所有需要的令牌,发送所有需要的操作以显示我们现在已登录
  4. 获取客户数据
  5. 根据参数和收到的数据,我们重定向到所需的路线/不要重定向
  6. 问题是测试真的太难了,而且我们需要将所有内容都存储起来,由于脆弱的测试,脆弱性和过多的实现知识而导致这种情况很糟糕(更不用说将调度发送到工作正常)。

    因此,我应该测试所有这5点,还是只关注最重要的东西,例如发送授权请求,抛出错误和检查重定向?我的意思是,所有标志的问题都可以改变,所以它不可靠。

    另一个解决方案就是将这些活动分成以下内容:

    • auth
    • setLoginInfo
    • handleRedirects

    并通过依赖注入传递所有需要的函数(这里只是使用params)?通过这种方法,我可以间谍只调用这些函数,而不需要详细介绍。

    我很熟悉纯函数的单元测试和为它们处理不同的边缘情况(没有测试太多的实现,只是结果),但是测试具有副作用的复杂函数对我来说真的很难。

1 个答案:

答案 0 :(得分:3)

如果你有这样非常复杂的动作,我认为另一种(更好的?)方法是改为采用简单的同步动作(你甚至可以直接调度有效载荷,如果你愿意,可以放弃动作创建者,减少锅炉板) ,并使用redux-saga处理异步端:https://github.com/yelouafi/redux-saga

Redux Saga可以非常简单地将您的业务逻辑代码分解为多个简单的生成器函数,这些函数可以单独进行测试。由于该库中的“调用”功能,它们也可以在没有调用底层API方法的情况下进行测试:http://yelouafi.github.io/redux-saga/docs/api/index.html#callfn-args。由于使用了生成器,您的测试可以使用标准的iterator.next方法将值“提供”给saga。最后,他们让减速者更容易发表意见,因为你可以从商店状态检查一些东西(例如使用选择器)来查看你的传奇中的下一步。

如果在我开始使用我的应用程序之前存在Redux + Redux Saga(目前大约有100,000个JS(X)LOC),我肯定会使用它们。