Мы использовали 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?





Кажется, есть несколько проблем с тем, что вы опубликовали.
Обновлять: Первоначально я думал, что вы используете старый выбор rxjs, но это было неверно. Убедитесь, что вы используете select from ngrx с таким импортом:
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% уверен, что это будет работать как есть, из-за всех неизвестных, которые я подробно описал выше. Надеюсь, это поможет по крайней мере указать вам правильное направление поиска ответа.
Я нашел этот вопрос, который показывает, что я дал неправильный совет относительно изменения выбранной карты. Я отредактирую свой ответ, чтобы отразить это. Также в этом посте рекомендуется импортировать такой вариант:
import { select } from '@ngrx/store';. Так ты это делаешь?