如何测试 redux-thunk 中间件异步功能?
Posted
技术标签:
【中文标题】如何测试 redux-thunk 中间件异步功能?【英文标题】:How to test redux-thunk middleware async functions? 【发布时间】:2016-04-24 00:25:27 【问题描述】:我正在尝试使用 mocha、chai 和 sinon 测试我的 asyn thunk 中间件 功能(我的第一次!)。
请考虑我的文件:
ayncActionCreators.js
export const fetchCurrentUser = () =>
return (dispatch) =>
setTimeout(dispatch, 100);
;
ayncActionCreators.spec.js
//...
it('Should work', () =>
const dispatch = sinon.spy();
const action = fetchCurrentUser();
action(dispatch);
expect(dispatch.called).to.be.true;
);
我还没有实现 fetchCurrentUser 函数 - 只是假设它需要一些“服务器”时间,然后它会调用 'dispatch()'。
由于异步流程,规范失败。如果我在期望之前添加 101 毫秒的 setTimeout - 它会通过。
我的代码将使用一些返回承诺的 DB API,因此异步函数最终将如下所示:
//...
return (dispatch) =>
return dbAPI.fetchUser().then(dispatch(....));
所以我尝试要求 dbAPI 并在测试中创建一个 sinon.stub().returns(Promise.resolve()) 并且它没有正常工作(我认为由于存根返回一个已解决的承诺 - async 函数将像同步函数一样工作)。
我应该如何测试这样的异步函数有什么想法吗?
谢谢, 阿米特。
【问题讨论】:
【参考方案1】:不要用 sinon 模拟 dispatch,写你自己的,完成后调用 Mocha 的done()
。
it('Should work', (done) =>
const dispatch = () =>
// Do your tests here
done();
;
const action = fetchCurrentUser();
action(dispatch)
// Also allow quick failures if your promise fails
.catch(done);
)
如果你只是想确保调度被调用,那么 mocha 将超时。对异步操作创建者返回的承诺的捕获允许错误显示在正确的位置,并且测试失败而不是超时。
【讨论】:
【参考方案2】:嗯,我想我找到了解决办法:
假设我的异步函数如下所示:
//...
return (dispatch) =>
return dbAPI.fetchUser().then(dispatch(....));
然后我可以编写如下规范:
it('Should work', () =>
dbAPI.fetchUser = sinon.stub().returns(Promise.resolve(username: 'John'));
const dispatch = sinon.spy();
const action = fetchCurrentUser();
action(dispatch).then(() =>
expect(dispatch.called).to.be.true;
);
);
我不知道这是否是一种解决方法,但它确实有效。我将不胜感激您对更好的方法的意见...
谢谢, 阿米特。
【讨论】:
这是在动作创建器中执行异步效果的不幸缺点之一,它们很难测试。如果坚持使用 redux-thunk 是您唯一的选择,那么这似乎是运行测试的最简洁方式。还有许多其他库可以使用 redux 执行异步操作,这有助于提高可测试性,并且如果您能够进行更改,则不需要您模拟您的 API,但是 如果您要做的只是确保调用了调度,那么这将起作用。如果您想测试调用什么调度(这可能更有意义),那么您可以使用 mocha 的done()
函数并编写自己的调度,正如我在回答中详述的那样。以上是关于如何测试 redux-thunk 中间件异步功能?的主要内容,如果未能解决你的问题,请参考以下文章
redux-thunk:错误:动作必须是普通对象。使用自定义中间件进行异步操作