【问题标题】:Redux-Observable testing readonly epicsRedux-Observable 测试只读史诗
【发布时间】:2021-11-13 22:17:21
【问题描述】:

我想测试以下史诗:

authEpics.logoutEpic = function (action$, _, deps) {
  return action$.pipe(
    ofType(authActions.logout),
    tap(() => {
      const { history, browser } = deps;
      browser.localStorage.removeItem('user');
      history.push(ROUTES.LOGIN);
    }),
    ignoreElements()
  );
};

这是测试用例:

describe('Logout Epic', () => {
  test('should remove user from localStorage', (done) => {
    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);
      
      // Statement 1.
      expectObservable(output$).toBe('');

      // Statement 2.
      output$.subscribe({
        complete: () => {
          expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
          expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
          done();
        }
      });
    });
});

根据ignoreElements 的定义,我无法理解以下观察结果:

  1. 在声明 1 中,我认为 expectObservable(output$).toBe('|') 应该可以工作,但事实并非如此。相反,expectObservable(output$).toBe('') 有效。
  2. 在语句 2 中,complete 函数永远不会被调用。

【问题讨论】:

    标签: redux redux-observable


    【解决方案1】:

    为了使测试用例工作,我必须刷新承诺队列(而不是使用expectObservable)。这是修改后的测试用例:

    describe('Logout Epic', () => {
      test('should remove user from localStorage', (done) => {
        scheduler.run(async (helpers) => {
          const { hot } = helpers;
          const action$ = hot('a', {
            a: authActions.logout(),
          });
          const deps = testUtils.mockEpicDependencies();
          const output$ = authEpics.logoutEpic(action$, null, deps);
    
          // *** Flush the promise queue ***
          await new Promise((resolve) => resolve());
    
          expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
          expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
    
          done();
        });
    });
    

    【讨论】:

      【解决方案2】:

      这太痛苦了,对我不起作用。

      const pingAuthEpic = (action$: any) => action$.pipe(
          ofType(SET_ONLINE),
          mergeMap(() => interval(PING_AUTH_INTERVAL).pipe(
              mergeMap(() => of({ type: 'PING_AUTH' })),
              takeUntil(action$.ofType(SET_OFFLINE)),
          )),
      );
      

      任何想法为什么它只是挂起并开玩笑超时欢迎......

      【讨论】:

      • 你能不能试着把takeUntil改成这样:takeUntil(action$.pipe(ofType(SET_OFFLINE)))如果不行,你能把测试用例代码贴在这里吗?
      • 嘿,谢谢 Anup - 我决定改为测试整个商店并只传递我想要测试的减速器和史诗......这要好得多,因为我不需要了解弹珠或任何东西我使用测试库的方式有问题。此外,如果我们远离未维护的 redux-observable,测试仍然可以工作。
      猜你喜欢
      • 2019-01-23
      • 2017-08-28
      • 1970-01-01
      • 2017-04-22
      • 2018-03-09
      • 2020-12-30
      • 2018-01-14
      • 2018-06-20
      • 2017-05-06
      相关资源
      最近更新 更多