angular2 测试中 fakeAsync 的 tick() 和 done() 有啥区别?
Posted
技术标签:
【中文标题】angular2 测试中 fakeAsync 的 tick() 和 done() 有啥区别?【英文标题】: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 而不是使用 async
或 fakeAsync
?
举个例子。
这个方法对我有用...
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);
));
注意:
数组 names
的数据是异步的,因为它是使用“get”操作从后端检索的。但在这里我是在嘲笑数据。
数组中的数据被遍历并传递给另一个子组件,在视图中显示它。
【问题讨论】:
这篇文章很好理解blog.nrwl.io/… @AngularInDepth.com 感谢您的链接!值得一读! 【参考方案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 方法,而 async
和 fakeAsync
是由 Angular 测试框架添加的
确实,您只能通过从angular/core/testing
导入async
和fakeAsync
来使用它们:)
@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();
));
【讨论】:
以上是关于angular2 测试中 fakeAsync 的 tick() 和 done() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
Angular2 NgModel 在 Jasmine 测试中没有获得价值
Angular 测试中的 fakeAsync 和 async 有啥区别?