【问题标题】:NGRX Effects testing with { dispatch: false }使用 { dispatch: false } 进行 NGRX 效果测试
【发布时间】:2019-04-20 20:54:21
【问题描述】:

我一直试图让这个工作好几个小时。这是我转换为 Jest 而不是 Karma 的第一个项目,到目前为止效果很好。我去为我的效果编写了一些测试,但无论出于何种原因,我完全无法以我期望的方式测试它们。

我要测试的效果是一个非常简单的导航:

@Effect({ dispatch: false })
go$ = this.actions$.pipe(
  ofType(RouterActions.GO),
  tap(
    ({ payload: { path, query: queryParams, extras } }: RouterActions.Go) => {
      this.router.navigate(path, { queryParams, ...extras });
    }
  )
);

我注入了一个假路由器,并打算测试它是否调用了导航,该测试已经经历了多次迭代以使其工作,但我目前拥有的是:

describe('Router Effects', () => {
  let actions$: Observable<any>;
  let router: TestRouter;
  let effects: RouterEffects;
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        RouterEffects,
        provideMockActions(() => actions$),
        {
          provide: Router,
          useFactory: getRouter
        }
      ]
    });

    actions$ = TestBed.get(Actions);
    router = TestBed.get(Router);
    effects = TestBed.get(RouterEffects);
  });

  describe('go$', () => {
    test('should call router.navigate with the correct path', done => {
      const action = new fromActions.Go({ path: ['some', 'path'] });

      actions$ = hot('-a', { a: action });
      const expected = cold('-b', { b: action });

      effects.go$.subscribe(
        result => {
          console.log('inside subscribe?');
          expect(router.navigate).toHaveBeenCalled();
          console.log('after expect');
          done();
          console.log('after done?');
        },
        done,
        done
      );

      expect(effects.go$).toBeObservable(expected);
    });
  });
});

当我运行该测试时,我在终端中得到以下结果:

FAIL  src/app/store/effects/router.effects.spec.ts (5.832s)
  ● Console

    console.log src/app/store/effects/router.effects.spec.ts:48
      inside subscribe?
    console.log src/app/store/effects/router.effects.spec.ts:50
      after expect
    console.log src/app/store/effects/router.effects.spec.ts:52
      after done?

  ● Router Effects › go$ › should call router.navigate with the correct path

    Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

我一直在努力弄清楚为什么没有调用异步回调?我在这里复制了一个最小的 repo:https://github.com/BenAychh/example-ngrx-effects-jest 并且有问题的代码位于此文件夹 https://github.com/BenAychh/example-ngrx-effects-jest/tree/master/src/app/store/effects 中。如果有人有兴趣在这里帮助我,您应该能够克隆整个 repo 并运行它并(希望)看看我所看到的。

【问题讨论】:

  • 您好,您解决了这个问题吗?我也遇到了。
  • 我最终放弃了 Jest 并搬回了 Karma,只是感觉还没有准备好。

标签: angular jestjs ngrx


【解决方案1】:

鉴于此效果:

@Injectable()
export class AuthEffects {
    @Effect({ dispatch: false })
    public logoutSuccess$ = this.actions$.pipe(
        ofType(AuthActionTypes.LogoutSuccess),
        tap(() => this.localStorage.removeItem(AUTH_FEATURE_KEY)),
        tap(() => this.router.navigate(['/']))
    );
}

这是我测试dispatch: false 效果的方法:

describe('logoutSuccess$', () => {
    it('should navigate and remove related data from local storage', () => {
        const action = new LogoutSuccess;
        actions$ = cold('-a', { a: action });

        expect(effects.logoutSuccess$).toBeObservable(actions$);
        expect(localStorageService.removeItem).toHaveBeenCalledWith(AUTH_FEATURE_KEY);
        expect(router.navigate).toHaveBeenCalledWith(['/']);
    });
});

.toBeObservable(actions$) 可以解决问题。

基于this answer

【讨论】:

  • 是的,我通常也是这样做的,但我无法让它与 jest-marbles 一起使用。不过与茉莉花大理石搭配效果很好。
猜你喜欢
  • 2018-06-27
  • 1970-01-01
  • 2019-06-23
  • 2023-03-13
  • 2019-06-22
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 2021-04-07
相关资源
最近更新 更多