Тестирование углового компонента, расширяющего абстрактный класс

#angular #jestjs #angular-components #angular-test #ngxs

#угловой #jestjs #угловые компоненты #угловой тест #ngxs

Вопрос:

У меня есть эта настройка для ряда компонентов:

 @Directive() export abstract class BaseComponent implements OnInit {   @Select(PortalState.portal) public portalState: Observablelt;PortalModelgt;;  public portal: PortalModel;  protected ngUnsubscribe: Subjectlt;voidgt; = new Subject();   constructor(  protected someService: SomeService,  protected route: ActivatedRoute  ){  }   public ngOnInit(): void {  this.route.params  .pipe(  filter(res =gt; !!res),  tap(res =gt; this.id = res['id']),  switchMap(() =gt; this.portalState),  takeUntil(this.ngUnsubscribe)  )  .subscribe(res =gt; {  this.portal = res;  this.afterInit();  });  }   public ngOnDestroy(): void {  this.ngUnsubscribe.next();  this.ngUnsubscribe.complete();  }   public abstract afterInit(): void }  

а затем в каждом компоненте, который расширяет этот базовый класс:

 @Component({...}) export class SomeComponent extends BaseComponent {   public specificVar: any;   constructor(  protected someService: SomeService,  protected route: ActivatedRoute  ){  super(someService, route);  }   public afterInit(): void {  /** do component specific stuff */  this.specificVar = 'something';  }  }  

Теперь это работает нормально, однако при тестировании ngOnInit абстрактного компонента, похоже, вообще не вызывается, отображая (в этом примере) this.specific переменную как неопределенную.

файл спецификации выглядит довольно традиционно

 let store: Store; /** Ngxs store */ const mockPortalModel: PortalModel = {id: 1};  beforeEach(async () =gt; {  TestBed.configureTestingModule(/** providers and usual setup */);  store = TestBed.inject(Store);  store.reset({  portalState: mockPortalModel  });  jest.spyOn(store, 'dispatch');  jest.spyOn(store, 'select'); });  beforeEach(() =gt; {  fixture = TestBed.createComponent(SomeComponent);  component = fixture.componentInstance;  fixture.detectChanges(); });  

Есть какие-нибудь идеи, почему ngOnInit и впоследствии afterInit не вызываются?

Ответ №1:

Вы должны написать ниже функцию в своем SomeComponent , чтобы она запускала ваш BaseComponent ngOnInit метод после SomeComponent ngOnInit метода.

 ngOnInit() {  super.ngOnInit(); }  

Комментарии:

1. Я не думаю, что это правда. Компонент компилируется и отлично работает сам по себе. Речь идет просто о том, чтобы проверить его там, где он терпит неудачу.

Ответ №2:

Проблема заключалась в this.route.params том, над чем нужно было издеваться, чтобы подписка могла сработать. Таким образом, насмешливый активированный маршрут решил проблему:

 const mockActivatedRoute = {  snapshot: {}, // needs to be there to avoid _lastPathIndex error  params: of({id: 123}) }  /** ... */ providers: [  {provide: ActivatedRoute, useValue: mockActivatedRoute } ]  

убедился, что подписка проходит (см. Это filter(res =gt; !!res) — она остановилась прямо там).