如何在Angular 7 ngrx 6.1中测试防护

时间:2018-11-29 11:45:49

标签: angular unit-testing redux karma-jasmine ngrx

我们使用Angular 5并将其更新为7。 目前,在pipe()中选择折线;

某些单元测试失败:

export class MyGuard  {
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
   
    this.store.dispatch(new Action());
    return this.store.pipe(
      select<IAppState>(getMainState),
      map((state: IState) => {
    this.router.navigate(['/', url]);
      }),
      catchError((a, b) => {
        this.router.navigate(['/', 'error']);
        return of(false);
      }),
    );
  }

和单元测试:

 it('should redirect to page ', inject(
    [MyGuard, Service],
    (guard: MyGuard, service: Service) => {
      spyOn(service, 'method').and.callFake(b => of({ id: { status: 'ok'} }));

      const route = new ActivatedRouteSnapshot();
      route.params = { id: '2' };
      const activation = guard.canActivate(route, {
        root: null,
        url: 'url',
      });

      if (activation instanceof Observable) {
        activation.subscribe(activationValue => {
          expect(activationValue).toBe(false);
expect(router.navigate).toHaveBeenCalled();

        });
      } else {
        fail('should not happen - should return an observable with true');
      }
    },
  ));

我们失败了,因为激活(guard.canActivate)不可观察。能否提供帮助并告诉您如何根据新的ngrx重构单元测试?

1 个答案:

答案 0 :(得分:1)

您发布的内容似乎存在一些问题。

更新:最初我认为您使用的是旧的rxjs select,但这是不正确的。确保您将ngrx中的select与这样的导入一起使用:

import { select } from '@ngrx/store';

如果您要求canActivate()返回一个Observable,则不要这样声明:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

而是这样声明:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {

另一个有问题的部分是:

map((state: IState) => {
     this.router.navigate(['/', url]);
}),

首先,它不返回任何内容,因此它破坏了可观察的链条-也许最简单的解决方法是删除花括号,以便从this.router.navigate()返回值。但是-本节中存在第二个问题:this.router.navigate返回一个诺言,而不是可观察的,因此,如果要在可观察的链中使用它,则需要用from包装它。最后,由于这本身就是一个Observable并返回一个Observable,因此您将根据需要使用mergeMapswitchMap之类的运算符。

我不确定您在catchError内要做什么,所以我不理会它,但是如果发生错误,您需要对其进行测试,以确保它能按预期运行

我还发现您当前的缩进非常令人困惑。

最后,您没有发布有关特定实现中this.store外观的详细信息。确保它返回一个可观察的! :)

将所有内容和一个可能的重构看起来像这样:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {

    this.store.dispatch(new Action());
    return this.store.pipe(
        select<IAppState>(getMainState),
        mergeMap((state: IState) => 
            from(this.router.navigate(['/', url]))
        ),
        catchError((a, b) => {
            this.router.navigate(['/', 'error']);
            return of(false);
        }),
    );
}

由于我上面详述的所有未知因素,我不到50%的信心能按原样工作。我希望这至少可以帮助您指出寻找答案的正确方向。