簡體   English   中英

測試 Angular 組件擴展抽象 class

[英]Testing Angular component extending an abstract class

我為許多組件設置了此設置:

@Directive()
export abstract class BaseComponent implements OnInit {

   @Select(PortalState.portal) public portalState: Observable<PortalModel>;
   public portal: PortalModel;
   protected ngUnsubscribe: Subject<void> = new Subject();

   constructor(
     protected someService: SomeService,
     protected route: ActivatedRoute
     ){
   }

   public ngOnInit(): void {
     this.route.params
     .pipe(
        filter(res => !!res),
        tap(res => this.id = res['id']),
        switchMap(() => this.portalState),
        takeUntil(this.ngUnsubscribe)
     )
     .subscribe(res => {
        this.portal = res;
        this.afterInit();
     });
   }

   public ngOnDestroy(): void {
       this.ngUnsubscribe.next();
       this.ngUnsubscribe.complete();
   }

   public abstract afterInit(): void
}

然后在擴展此基礎 class 的每個組件中:

@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 () => {
  TestBed.configureTestingModule(/** providers and usual setup */);
  store = TestBed.inject(Store);
  store.reset({
    portalState: mockPortalModel
  });
  jest.spyOn(store, 'dispatch');
  jest.spyOn(store, 'select');
});

beforeEach(() => {
   fixture = TestBed.createComponent(SomeComponent);
   component = fixture.componentInstance;
   fixture.detectChanges();
});

有什么想法為什么不調用ngOnInit和隨后的afterInit嗎?

您必須在 SomeComponent 的SomeComponent ,以便它在SomeComponentngOnInit方法之后運行您的BaseComponentngOnInit方法。

ngOnInit() {
  super.ngOnInit();
}

問題出在必須模擬的this.route.params中,因此訂閱可能會觸發。 所以mocking激活路由解決了這個問題:

const mockActivatedRoute = {
  snapshot: {}, // needs to be there to avoid _lastPathIndex error
  params: of({id: 123})
}

/** ...  */
providers: [
  {provide: ActivatedRoute, useValue: mockActivatedRoute }
]

已確保訂閱通過(請參閱filter(res => !!res) - 它就停在那里)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM