Angular:返回可观察值的测试防护

时间:2018-11-08 16:02:50

标签: angular unit-testing jasmine rxjs karma-runner

我正在尝试测试可返回可观察值并调用另一个函数的身份验证防护。我的后卫看起来像这样(从托德·莫托(Todd Motto)提起。

@Injectable()
export class ProductSummaryLoadedGuard implements CanActivate {
  constructor(private store: Store<fromProductStore.State>) {}

  canActivate(): Observable<boolean> {
    return this.checkStore().pipe(
      switchMap(() => of(true)),
      catchError(() => of(false))
    );
  }

  checkStore(): Observable<boolean> {
    return this.store.pipe(select(fromProductStore.selectProductLoaded)).pipe(
      tap(loaded => {
        if (!loaded) {
          this.store.dispatch(new fromProductStore.LoadProductSummary());
        }
      }),
      filter(loaded => loaded),
      take(1)
    );
  }
}

为此,我整理了规范的框架,引起问题的摘要如下:

it('should return true when checkStore() returns true', () => {
  spyOn(guard, 'checkStore').and.returnValue(of(true));

  const result = guard.canActivate();
  expect(result).toBeObservable(of(true));
});

执行此规范时,我在Karma中遇到此错误:

  

TypeError:无法读取未定义的属性'indexOf'      在Function.TestScheduler.parseMarbles(./node_modules/rxjs/_esm5/internal/testing/TestScheduler.js?:243:21)

我在这里想念什么?我不想仅仅针对这种方法使用大理石测试,但是如果有人可以提出建议,那么我很乐意尝试!

1 个答案:

答案 0 :(得分:2)

来自NgRx的示例Effect testing代码显示了使用toBeObservable的方式:

const expected = hot('-------a', {
  a: {
    type: '[Customers API] Search Customers Success',
    customers: [...],
  },
});

expect(
  effects.searchCustomers$({
    debounce: 20,
    scheduler: getTestScheduler(),
  })
).toBeObservable(expected);

.toBeObservable()期望具有TestHotObservable属性的TestColdObservablemarbles。我到达这里是因为在没有参数的情况下使用TypeError: Cannot read property 'marbles' of undefined导致出现.toBeObservable()错误。

如果您要使用非TestXXXObservable类型的可观察对象进行测试,则必须订阅它们并验证订阅中的结果,如NgRx testing example所示:

// create an actions stream and immediately dispatch a GET action
actions$ = of({ type: '[Customers Page] Get Customers' });

// mock the service to prevent an HTTP request
customersServiceSpy.getAllCustomers.and.returnValue(of([...]));

// subscribe to the Effect stream and verify it dispatches a SUCCESS action
effects.getAll$.subscribe(action => {
  expect(action).toEqual({
    type: '[Customers API] Get Customers Success',
    customers: [...],
  });
});