Как протестировать охранников в Angular 7 ngrx 6.1

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

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
763
1

Ответы 1

Кажется, есть несколько проблем с тем, что вы опубликовали.

Обновлять: Первоначально я думал, что вы используете старый выбор 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';. Так ты это делаешь?

dmcgrandle 04.12.2018 19:00

Другие вопросы по теме