【问题标题】:Angular 6 Unit Test ngOnInit with a setTimeOut not working带有setTimeOut的Angular 6单元测试ngOnInit不起作用
【发布时间】:2019-06-17 14:01:59
【问题描述】:

我在 ngOnInit 函数中有一个带有 setTimeOut 函数的组件。要为此编写单元测试用例,我使用 tick 和 fakeAsync 来快进 setTimeOut。但是,它没有被执行,这反过来又没有调用其他函数 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>

【问题讨论】:

    标签: angular unit-testing angular5 angular6 angular-unit-test


    【解决方案1】:

    我在代码中看到了几个问题。

    • 在您在component.errorData 中设置有效数据之前,您正在调用component.ngOnInit()fixture.detectChanges()(也将调用ngOnInit)。
    • 我不清楚您为什么期望banner 在您显示的html 中为空。因此,我将测试更改为看到 component.closeAlert() 已被调用,如果 component.errorData 已重置为 null,因为这似乎是您真正想要测试的内容。为了测试这一点,我监视了component.closeAlert()
    • 我通过在tick(499) 之后进行测试,然后再进行一次滴答后,将滴答声设置为准确显示拨打component.closeAlert() 的时间...

    工作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)
      // });
    }));
    

    我希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-08
      • 2020-08-21
      • 1970-01-01
      • 2021-09-25
      • 2017-01-19
      • 1970-01-01
      • 2019-03-24
      • 1970-01-01
      相关资源
      最近更新 更多