测试包含setTimeout()的函数

ed-*_*ter 29 testing settimeout jasmine karma-jasmine angular

我的组件中有一个包含a的close函数 setTimeout()以便给动画完成时间.

public close() {
    this.animate = "inactive"
    setTimeout(() => {
       this.show = false
    }, 250)
}
Run Code Online (Sandbox Code Playgroud)

this.show 必然是一个 ngIf.

this.animate 绑定动画.

我有一个需要测试此功能的测试

it("tests the exit button click", () => {
  comp.close()
  fixture.detectChanges()
  //verifies the element is no longer in the DOM
  const popUpWindow = fixture.debugElement.query(By.css("#popup-window"))
  expect(popUpWindow).toEqual(null)
})
Run Code Online (Sandbox Code Playgroud)

如果有的话,你如何正确测试这个功能? setTimeout()

我正在使用,jasmine.clock().tick(251)但窗户永远不会消失.对此有何想法?

Mez*_*van 59

你可以做两件事之一:

1:实际上在测试中等待250 + 1 ms setTimeout(),然后检查元素是否实际消失.

2:使用fakeAsync()tick()模拟测试中的时间 - 一个tick()将解析原始中的setTimeout close(),并且检查可能在a之后发生fixture.whenStable().then(...).

例如:

it("tests the exit button click", fakeAsync(() => {
  comp.close()
  tick(500)
  fixture.detectChanges()

  fixture.whenStable().then(() => {
    const popUpWindow = fixture.debugElement.query(By.css("#popup-window"))
    expect(popUpWindow).toBe(null)
  })
}))
Run Code Online (Sandbox Code Playgroud)

我建议使用第二个,因为它比实际等待原始方法快得多.如果仍然使用1st,请尝试在测试之前降低超时时间,以使其运行得更快.

  • 除此之外,在*tick之前你可能还需要一个额外的`fixture.detectChanges()`*.那么你可能根本不需要`fixture.whenStable()`(afaik fakeAsync的设计正是为了避免这种异步调用). (2认同)
  • 如果它帮助其他任何人,则需要在fakeAsync方法中调用调用setTimeout的函数(不能在beforeEach中调用).看起来很明显,但它让我! (2认同)

Kai*_*las 18

在我的组件中,方法是:

hideToast() {
    setTimeout( () => {
      this.showToast = false;
    }, 5000);
  }
Run Code Online (Sandbox Code Playgroud)

对此进行测试(评论中的解释):

it('should hide toast', () => {
  component.showToast = true; // This value should change after timeout
  jasmine.clock().install();  // First install the clock
  component.hideToast();      // Call the component method that turns the showToast value as false
  jasmine.clock().tick(5000); // waits till 5000 milliseconds
  expect(component.showToast).toBeFalsy();  // Then executes this
  jasmine.clock().uninstall(); // uninstall clock when done
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!!


小智 5

刚刚在我的项目中尝试过这个并且有效:

jasmine.clock().tick(10);
Run Code Online (Sandbox Code Playgroud)


小智 5

我有一个与OP的设置非常相似的方法,所以我想添加我的测试,我认为这要简单得多。

** 方法 **

public close() {
    this.animate = "inactive"
    setTimeout(() => {
       this.show = false
    }, 250)
}
Run Code Online (Sandbox Code Playgroud)

** 茉莉花测试 **

it('should set show to "false" after 250ms when close is fired', (done) => {
      component.close();
      setTimeout(() => {
        expect(component.close).toBeFalse();
        done();
      }, 251);
    });
Run Code Online (Sandbox Code Playgroud)

请注意,使用“done”让 jasmine 知道测试已完成,并在 setTimeout 中添加 1 毫秒,以便在我的方法的 setTimeout 之后触发。