如何测试依赖于先前调度调用的异步操作创建者?

How do I test asynchronous action creators that rely on previous dispatch calls?

我有一个异步动作创建器,它分为两个动作,一个表示动作开始,另一个表示动作结束。异步action creator中间的web请求依赖第一个同步dispatch设置的值:

export function changeFilter(from, to) {
  return (dispatch, getState, { fetch }) => {
    // Updates the state with the new values and sets a loading flag
    dispatch(changeFilterRequest(from, to));

    // Now I want to use those newly-set values to build a query
    // string. However, the stubbed implementation of `dispatch`
    // doesn't use reducers, so `getState` continues to return the
    // original value.
    const { activeUsers } = getState();
    return doSomeWebRequest(fetch, activeUsersParams(activeUsers))
      .then(response => dispatch(changeFilterSuccess(response)))
  };
}

implementation of redux-mock-store's dispatch 非常稀疏,事后看来(很明显),我们从未将任何 reducer 传递给模拟存储。

这意味着第一个 dispatch 调用没有机会更新第二个调度调用所依赖的状态。然后,我们发出的 Web 请求具有 tofrom 日期的原始值,而不是来自异步操作调用的更新值。

我想避免直接使用传递给 changeFilterfromto 值,因为可能会对 changeFilterRequest 中的参数应用进一步的转换.直接依赖 getState 的结果也可以让我干掉少数以不同方式过滤的类似方法。

对于这些类型的测试,我应该遵循哪些模式?我应该用不同的方式来构建我的动作创作者吗?

我认为你的单元测试应该是精确的,只关注你想要测试的功能范围,即 changeFilter。假设您有另一个针对 changeFilterRequest 的单元测试,测试 activeUsers 是如何计算并添加到商店的,事实上 activeUsers 是在商店中创建的,作为调度 [=11] 的副作用=] 应该超出您的测试范围,因为 changeFilter 不应该关心 activeUsers 是如何计算的。我认为你可以安全地在你的模拟商店中为 activeUsers 添加任何虚拟值,它不一定依赖于你传递给 changeFilterRequest 和 make 的 tofrom 的值确保您的函数正在从商店正确读取该值并将其传递给 activeUsersParams.

也就是说,我强烈推荐 redux-saga 作为 redux-thunk 的替代方法来处理异步操作,因为它使测试这类操作变得容易,而无需创建模拟或测试副作用,因为所有你的行为将是纯洁的。