【问题标题】:What is the difference between fakeAsync's tick() and done() in angular2 testing?angular2 测试中 fakeAsync 的 tick() 和 done() 有什么区别?
【发布时间】:2018-04-01 07:24:21
【问题描述】:

我正在尝试找出 fakeAsync 的 tick() 方法与 done() 的区别,正如一些 answers 在堆栈溢出时所建议的那样。

使用tick() 我们可以模拟超时,但是我们可以使用done() 来实现同样的效果吗?

为什么 Angular 认为 more viable method 而不是使用 asyncfakeAsync

举个例子。

这个方法对我有用...

it("Should display names",(done:any) => {
        component.names = [
            {
                "firstname": "abc",
                "lastname": "max"
            },
            {
                "firstname": "def",
                "lastname": "max"
            },
        ];
        done();
        fixture.detectChanges();
        let wrapBox = fixture.debugElement.queryAll(By.css('.wrapBox'));
        console.log(wrapBox);
});

但以下方法返回 '6 timer(s) still in queue' 错误...

it("Should display names",fakeAsync(() => {
        component.names = [
            {
                "firstname": "abc",
                "lastname": "max"
            },
            {
                "firstname": "def",
                "lastname": "max"
            },
        ];
        tick();
        fixture.detectChanges();
        let wrapBox = fixture.debugElement.queryAll(By.css('.wrapBox'));
        console.log(wrapBox);
}));

注意

  1. 数组 names 的数据是异步的,因为它是使用“get”操作从后端检索的。但在这里我是在嘲笑数据。

  2. 数组中的数据被遍历并传递给另一个子组件,在视图中显示它。

【问题讨论】:

  • 这篇文章很好理解blog.nrwl.io/…
  • @AngularInDepth.com 感谢您的链接!值得一读!

标签: angular unit-testing typescript karma-jasmine


【解决方案1】:

这两件事没有共同点。

done 只是一个回调,让您的测试运行器知道异步操作何时完成。

例如:

it('should wait for this promise to finish', done => {
  const p = new Promise((resolve, reject) =>
    setTimeout(() => resolve(`I'm the promise result`), 1000)
  );

  p.then(result => {
    // following will display "I'm the promise result" after 1s
    console.log(result);

    // this let your test runner know that it can move forward
    // because we're done here
    // the test will take 1s due to the setTimeout at 1000ms
    done();
  });
});

您也可以为此使用async(只是为了避免手动调用done):

it(
  'should wait for this promise to finish',
  async(() => {
    const p = new Promise((resolve, reject) =>
      setTimeout(() => resolve(`I'm the promise result`), 1000)
    );

    p.then(result =>
      // following will display "I'm the promise result" after 1s
      console.log(result)
    );

    // notice that we didn't call `done` here thanks to async
    // which created a special zone from zone.js
    // this test is now aware of pending async operation and will wait
    // for it before passing to the next one
  })
);

现在,fakeAsync 让您可以控制时间(这真的很强大),因此您可以以同步方式编写测试,并模拟时间流逝以避免等待 setTimeout,例如:

it(
  'should wait for this promise to finish',
  fakeAsync(() => {
    const p = new Promise((resolve, reject) =>
      setTimeout(() => resolve(`I'm the promise result`), 1000)
    );

    // simulates time moving forward and executing async tasks
    flush();

    p.then(result =>
      // following will display "I'm the promise result" **instantly**
      console.log(result)
    );

    // notice that we didn't call `done` here has there's no async task pending
  })
);

所以要明确一点,在上一个示例中使用 fakeAsync,如果 setTimeout 设置为 10 秒,测试仍会立即执行

【讨论】:

  • 你也可以添加 done 是原生 Jasmine 方法,而 asyncfakeAsync 是由 Angular 测试框架添加的
  • 确实,您只能通过从angular/core/testing 导入asyncfakeAsync 来使用它们:)
  • @Maxime 很好的解释!谢谢!
  • 这个故事中提到的 tick() 在哪里?
  • Tick 与同花顺几乎相同。 Flush 将运行队列中的所有异步任务,如果没有提供参数,也会运行。但是你也可以决定以毫秒为单位消磨时间,它会运行那些只应该在这段时间内运行的任务。因此,例如,如果您必须设置超时,一个在 2 秒,另一个在 1,运行 tick(1000),只会调用第一个回调。
【解决方案2】:

我做了一个小测试,帮助我了解 tick 可以做什么:

it('should tell me what tick can do...', fakeAsync(() => {
    let counter1 = 0;
    let counter2 = 0;
    let intervalTime = 1000;
    let passingTime = intervalTime*5;

    interval(intervalTime).subscribe(() => {
        counter1++;
    });

    setInterval(() => {
        counter2++;
    }, intervalTime);

    expect(counter1).toBe(0);
    expect(counter2).toBe(0);

    let now = new Date().getTime();
    tick(passingTime);
    let later = new Date().getTime();

    expect(now).toBe(later-passingTime)

    expect(counter1).toBe(5);
    expect(counter2).toBe(5);

    discardPeriodicTasks();
}));

【讨论】:

    猜你喜欢
    • 2019-04-25
    • 2017-08-15
    • 2019-10-23
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 2014-11-19
    • 2012-02-09
    • 2016-04-15
    相关资源
    最近更新 更多