我们使用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重构单元测试?
答案 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,因此您将根据需要使用mergeMap
或switchMap
之类的运算符。
我不确定您在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%的信心能按原样工作。我希望这至少可以帮助您指出寻找答案的正确方向。