代码之家  ›  专栏  ›  技术社区  ›  Varun

角度6单位测试,设置超时无效

  •  0
  • Varun  · 技术社区  · 6 年前

    我有一个组件,在ngoninit函数内部有一个setTimeout函数。为了编写单元测试用例,我使用Tick和FakeAsync快速转发设置超时。但是,它不会被执行,而这反过来又不会调用其他函数closeAlert()。

    组件代码:

    export class BannerComponent implements OnInit {
    
      @Input()errorData: any;
    
      @Input()callback: any;
    
      @Input()autoHide: boolean;
    
      constructor() { }
    
      ngOnInit() {
    
        if (this.autoHide) {
          setTimeout
            (() => {
              this.closeAlert();
            }, 500);
        }
      }
    
      closeAlert() {
        this.errorData = null;
        if (this.callback) {
          this.callback();
        }
      };
    }
    

    规格文件:

    describe('BannerComponent', () => {
      let component: BannerComponent;
      let fixture: ComponentFixture<BannerComponent>;
    
      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ BannerComponent ]
        })
        .compileComponents();
      }));
    
      beforeEach(async() => {
        fixture = TestBed.createComponent(BannerComponent);
        component = fixture.componentInstance;
        component.ngOnInit();
        fixture.detectChanges();
      });
    
      it("banner should hide after 500ms", fakeAsync(() => {
        component.errorData = {
          _statusMessage: "New alert banner",
          _statusCode: '200',
        };
        component.callback = null;;
        component.autoHide = true;
    
        tick(600);
        fixture.detectChanges()
    
        fixture.whenStable().then(() => {
          let banner = fixture.debugElement.query(By.css('.success'));
          expect(banner).toBe(null)
        })
      }));
    
    });
    

    HTML代码:

    <div class="success">
        <p>{{errorData._statusMessage}}</p>
    </div>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   dmcgrandle    6 年前

    我在代码中看到了一些问题。

    • 你们两个都打 component.ngOnInit() fixture.detectChanges() (也将称为ngoninit)在中设置有效数据之前 component.errorData .
    • 我不清楚你为什么期待 banner 显示的HTML为空。因此我把测试改为看 component.closeAlert() 被召唤,如果 组件错误数据 已经重置为空,因为这似乎是您真正想要测试的。为了测试我所监视的 组件。CloseAlert()) .
    • 我设置了刻度以精确显示呼叫的时间 组件。CloseAlert()) 通过测试之后 tick(499) ,然后再打一个勾…

    工作 StackBlitz .

    代码:

    beforeEach(async(() => { // slight correction of incorrect async wrapper ...
      fixture = TestBed.createComponent(BannerComponent);
      component = fixture.componentInstance;
      // component.ngOnInit(); // <-- don't call this here, the data isn't set up yet ...
      // fixture.detectChanges(); // ditto
    }));
    
    it("banner should hide after 500ms", fakeAsync(() => {
      spyOn(component, 'closeAlert').and.callThrough(); // set up a spy so we can test later
      component.errorData = {
        _statusMessage: "New alert banner",
        _statusCode: '200',
      };
      component.callback = null;;
      component.autoHide = true;
    
      fixture.detectChanges(); // <-- this will execute ngOnInit()
      expect(component.errorData).not.toBeNull(); // <-- after ngOnInit, still NOT null
      expect(component.closeAlert).not.toHaveBeenCalled();
      tick(499); // <-- now let 499ms pass ...
      expect(component.errorData).not.toBeNull(); // <-- after all that "fake" time, still NOT null
      expect(component.closeAlert).not.toHaveBeenCalled();
      tick(1); // <-- now tick for just 1 more millisecond ...
      expect(component.errorData).toBeNull(); // <-- now this has become NULL
      expect(component.closeAlert).toHaveBeenCalled(); // <-- and the method was called
      // fixture.whenStable().then(() => {
      //   let banner = fixture.debugElement.query(By.css('.success'));
      //   expect(banner).toBe(null)
      // });
    }));
    

    希望这有帮助!