Redux-Observable测试logout epic时ignoreElements相关问题咨询
问题原因解答
1. 为什么expectObservable(output$).toBe('|')不生效,只有toBe('')能通过
你构造的热 Observable 用的弹珠串是'a',仅代表第0帧发出authActions.logout()这个next事件,该 Observable 本身不会触发complete通知。ignoreElements的逻辑是仅过滤上游传来的所有next通知,不会主动生成complete通知,只有上游触发complete的时候,它才会把complete通知向下传递。你的上游action$从来不会complete,自然output$也永远不会触发complete,所以期望有complete事件的'|'肯定无法通过测试,''代表没有任何事件(next、complete、error)发出,才符合实际表现。
2. 为什么语句2的complete回调永远不会触发
和上一个问题是同一个根因:output$永远不会触发complete通知,所以订阅时传入的complete回调函数永远不会被执行,甚至会导致测试因超时报错。
正确的测试写法
你可以从两种方案里选一种适配你的测试场景:
方案1:给测试用的action$补全complete通知
如果你希望测试完整的生命周期,把弹珠串改成'a|'即可:
const action$ = hot('a|', { a: authActions.logout(), });
修改后上游action$在发出logout事件后会立刻触发complete,此时:
expectObservable(output$).toBe('|')可以正常通过- complete回调会正常触发,
done()也能被正常调用
方案2:直接断言副作用,不需要等待complete
实际生产环境中,epic绑定的store action流是永远不会complete的,更贴近实际运行逻辑的写法是不需要监听complete,直接在scheduler执行完成后断言副作用即可:
describe('Logout Epic', () => { test('should remove user from localStorage', () => { scheduler.run((helpers) => { const { hot, expectObservable } = helpers; const action$ = hot('a', { a: authActions.logout(), }); const deps = testUtils.mockEpicDependencies(); const output$ = authEpics.logoutEpic(action$, null, deps); expectObservable(output$).toBe(''); // 直接断言副作用即可,不需要等complete expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user'); expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN); }); }); });
内容的提问来源于stack exchange,提问作者Anup Vasudeva
相关产品推荐
相关产品推荐

