如何在ngOnit方法内编写用于订户和超时的测试用例?

问题描述

我使用以下ngOnit方法在angular8应用程序中有一个

  ngOnInit(): void {
    this.setCustomizedValues();
    this.sub = PubSub.subscribe('highlightEntity',(subId,entityIdentifier: string) => {
      document.querySelector(entityIdentifier).classList.add('highlight');

      setTimeout(() => {
        document.querySelector(entityIdentifier).classList.remove('highlight');
      },2000);

    });
  }

我已经初始化了以下测试用例

describe('aComponent',() => {

    
  let httpCallerServiceStub = jasmine.createSpyObj('httpCallerServiceStub',['get']);

  let fixture: ComponentFixture<aComponent>;
  let componentInstance: aComponent;
  localStorage.clear();
  beforeEach(() => {
    Testbed.configureTestingModule({
      declarations: [aComponent],providers: [
        {
          provide: HttpCallerService,useValue: httpCallerServiceStub
        }],imports: [CommonModule,CmcSpinnerModule,NgbModule],}).compileComponents();

    fixture = Testbed.createComponent(aComponent);
    componentInstance = fixture.componentRef.instance;
    fixture.autoDetectChanges();
  });

 describe('ngOnInit method',() => {
    beforeEach(() => {
      fixture.componentInstance.customized = {};
    });

    it('should initialize with minimum input',() => {
      // Triggers ngOnInit
      fixture.detectChanges();
      expect(fixture.componentInstance.customized).toEqual({});
    });
  });

所以当我运行它时,它会随机抛出以下错误

 "message": "An error was thrown in afterall\nTypeError: Cannot read property 'classList' of null\n    at <Jasmine>\n    at webpack:///components/aComponent/aComponent.ts:33:53 

这是业力测试运行程序中的控制台错误

enter image description here

这是文件的建议

enter image description here

因此,在此之后,无论我提前写了多少测试,问题仍然保持不变,有时可行,有时不可行。

您能告诉我ngonit内部的pubsub.subscriber和超时怎么办吗?

解决方法

由于您对DOM感到困惑,因此ngOnInit可能为时过早。 DOM尚未绘制。尝试将逻辑移至ngAfterViewInit

ngAfterViewInit() {
    this.sub = PubSub.subscribe('highlightEntity',(subId,entityIdentifier: string) => {
      document.querySelector(entityIdentifier).classList.add('highlight');

      setTimeout(() => {
        document.querySelector(entityIdentifier).classList.remove('highlight');
      },2000);
    });
}

要测试setTimeout,可以使用fakeAsynctick

import { fakeAsync,tick } from '@angular/core/testing';
...
it('should initialize with minimum input',fakeAsync(() => {
      // Triggers ngOnInit
      fixture.detectChanges();
      // do your assertions for ngAfterViewInit
      // make 2s pass in a fake way
      tick(2000);
      // do your assertions for the setTimeout callback
      expect(fixture.componentInstance.customized).toEqual({});
    }));