带有setTimeOut的Angular 6单元测试ngOnInit不起作用 [英] Angular 6 Unit Test ngOnInit with a setTimeOut not working

查看:254
本文介绍了带有setTimeOut的Angular 6单元测试ngOnInit不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ngOnInit函数内部有一个带有setTimeOut函数的组件.为此,我要使用tick和fakeAsync来编写单元测试用例,以快速转发setTimeOut.但是,它没有被执行,因此又没有调用其他函数closeAlert().

I have a component with a setTimeOut function inside a ngOnInit function. To write unit test cases for that I'm using tick and fakeAsync to fast forward the setTimeOut. But, it's not getting executed which in turn is not calling other function 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>

推荐答案

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

A couple of issues I saw with the code.

  • component.errorData中设置有效数据之前,您要同时调用component.ngOnInit()fixture.detectChanges()(也将调用ngOnInit).
  • 我不清楚为什么您期望banner在显示的html中为空.因此,我将测试更改为看到component.closeAlert()被调用,并且如果component.errorData被重置为null,因为看来这正是您真正想要测试的东西.为了对此进行测试,我在component.closeAlert()上进行了监视.
  • 我通过在tick(499)之后进行测试,然后再进行一次滴答之后的测试,来设置刻度,以准确显示何时调用component.closeAlert().
  • You are calling both component.ngOnInit() and fixture.detectChanges() (which will also call ngOnInit) BEFORE you have set up valid data in component.errorData.
  • It is unclear to me why you are expecting banner to be null with the html you have shown. I therefore changed the test to seeing component.closeAlert() had been called, and if component.errorData had been reset to null, since it appears that is what you are really wanting to test. To test for this I spied on component.closeAlert().
  • I set up the ticks to show exactly when the call is made to component.closeAlert() by testing after tick(499), and then after one more tick ...

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

我希望这会有所帮助!

这篇关于带有setTimeOut的Angular 6单元测试ngOnInit不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆