如何测试依赖于先前调度调用的异步操作创建者?
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 请求具有 to
和 from
日期的原始值,而不是来自异步操作调用的更新值。
我想避免直接使用传递给 changeFilter
的 from
和 to
值,因为可能会对 changeFilterRequest
中的参数应用进一步的转换.直接依赖 getState
的结果也可以让我干掉少数以不同方式过滤的类似方法。
对于这些类型的测试,我应该遵循哪些模式?我应该用不同的方式来构建我的动作创作者吗?
我认为你的单元测试应该是精确的,只关注你想要测试的功能范围,即 changeFilter
。假设您有另一个针对 changeFilterRequest
的单元测试,测试 activeUsers
是如何计算并添加到商店的,事实上 activeUsers
是在商店中创建的,作为调度 [=11] 的副作用=] 应该超出您的测试范围,因为 changeFilter
不应该关心 activeUsers
是如何计算的。我认为你可以安全地在你的模拟商店中为 activeUsers
添加任何虚拟值,它不一定依赖于你传递给 changeFilterRequest
和 make 的 to
和 from
的值确保您的函数正在从商店正确读取该值并将其传递给 activeUsersParams
.
也就是说,我强烈推荐 redux-saga
作为 redux-thunk
的替代方法来处理异步操作,因为它使测试这类操作变得容易,而无需创建模拟或测试副作用,因为所有你的行为将是纯洁的。
我有一个异步动作创建器,它分为两个动作,一个表示动作开始,另一个表示动作结束。异步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 请求具有 to
和 from
日期的原始值,而不是来自异步操作调用的更新值。
我想避免直接使用传递给 changeFilter
的 from
和 to
值,因为可能会对 changeFilterRequest
中的参数应用进一步的转换.直接依赖 getState
的结果也可以让我干掉少数以不同方式过滤的类似方法。
对于这些类型的测试,我应该遵循哪些模式?我应该用不同的方式来构建我的动作创作者吗?
我认为你的单元测试应该是精确的,只关注你想要测试的功能范围,即 changeFilter
。假设您有另一个针对 changeFilterRequest
的单元测试,测试 activeUsers
是如何计算并添加到商店的,事实上 activeUsers
是在商店中创建的,作为调度 [=11] 的副作用=] 应该超出您的测试范围,因为 changeFilter
不应该关心 activeUsers
是如何计算的。我认为你可以安全地在你的模拟商店中为 activeUsers
添加任何虚拟值,它不一定依赖于你传递给 changeFilterRequest
和 make 的 to
和 from
的值确保您的函数正在从商店正确读取该值并将其传递给 activeUsersParams
.
也就是说,我强烈推荐 redux-saga
作为 redux-thunk
的替代方法来处理异步操作,因为它使测试这类操作变得容易,而无需创建模拟或测试副作用,因为所有你的行为将是纯洁的。