問(wèn)題描述
我正在嘗試從 Angular 2 中的模擬后端獲取結(jié)果以進(jìn)行單元測(cè)試.目前,我們正在使用帶有超時(shí)的 fakeAsync
來(lái)模擬時(shí)間的流逝.
I'm trying to get the results from a mock backend in Angular 2 for unit testing. Currently, we are using fakeAsync
with a timeout to simulate the passing of time.
當(dāng)前工作單元測(cè)試
it('timeout (fakeAsync/tick)', fakeAsync(() => {
counter.getTimeout();
tick(3000); //manually specify the waiting time
}));
但是,這意味著我們僅限于手動(dòng)定義的超時(shí).不是在異步任務(wù)完成時(shí).我想做的是讓 tick()
等到任務(wù)完成后再繼續(xù)測(cè)試.
But, this means that we are limited to a manually defined timeout. Not when the async task is completed. What I'm trying to do is getting tick()
to wait until the task is completed before continuing with the test.
這似乎沒(méi)有按預(yù)期工作.
This does not seem to work as intended.
閱讀 fakeAsync
和 tick
答案這里 解釋說(shuō):
Reading up on the fakeAsync
and tick
the answer here explains that:
tick() 模擬時(shí)間的異步流逝.
tick() simulates the asynchronous passage of time.
我設(shè)置了一個(gè) plnkr 示例來(lái)模擬這種情況.
I set up a plnkr example simulating this scenario.
在這里,我們調(diào)用 getTimeout()
方法,該方法調(diào)用具有超時(shí)的內(nèi)部異步任務(wù).在測(cè)試中,我們嘗試包裝它并在調(diào)用 getTimeout()
方法后調(diào)用 tick()
.
Here, we call the getTimeout()
method which calls an internal async task that has a timeout. In the test, we try wrapping it and calling tick()
after calling the getTimeout()
method.
counter.ts
getTimeout() {
setTimeout(() => {
console.log('timeout')
},3000)
}
counter.specs.ts
it('timeout (fakeAsync/tick)', fakeAsync(() => {
counter.getTimeout();
tick();
}));
但是,單元測(cè)試失敗并出現(xiàn)錯(cuò)誤錯(cuò)誤:1 個(gè)計(jì)時(shí)器仍在隊(duì)列中."
But, the unit test fails with the error "Error: 1 timer(s) still in the queue."
角度回購(gòu)中的問(wèn)題是否與此有關(guān)?
Does the issue here in the angular repo have anything to do with this?
是否可以這樣使用tick()
來(lái)等待超時(shí)函數(shù)?還是我可以使用另一種方法?
Is it possible to use tick()
this way to wait for a timeout function? Or is there another approach that I can use?
推薦答案
fakeAsync
的目的是在你的規(guī)范內(nèi)控制時(shí)間.tick
不會(huì)等待任何時(shí)間,因?yàn)樗怯糜谀M時(shí)間流逝的同步函數(shù).如果您想等到異步功能完成,您將需要使用 async
和 whenStable
,但是,在您的示例中,規(guī)范需要 3 秒才能完成通過(guò),所以我不建議這樣做.
The purpose of fakeAsync
is to control time within your spec. tick
will not wait for any time as it is a synchronous function used to simulate the passage of time. If you want to wait until the asynchronous function is complete, you are going to need to use async
and whenStable
, however, in your example, the spec will take 3 seconds to pass so I wouldn't advise this.
counter.spec.ts 失敗的原因是您只模擬了 0 秒的過(guò)去(通常用于表示事件循環(huán)的下一個(gè)滴答聲).因此,當(dāng)規(guī)范完成時(shí),仍然有模擬的計(jì)時(shí)器處于活動(dòng)狀態(tài),這使整個(gè)規(guī)范失敗.通過(guò)通知您超時(shí)已被模擬并且未處理,它實(shí)際上可以正常工作.
The reason why the counter.spec.ts is failing is that you have only simulated the passage of 0 seconds (typically used to represent the next tick of the event loop). So when the spec completes, there are still mocked timers active and that fails the whole spec. It is actually working properly by informing you that a timeout has been mocked an is unhandled.
基本上,我認(rèn)為您正在嘗試以不打算使用它們的方式使用 fakeAsync
和 tick
.如果您需要按照您建議的方式測(cè)試超時(shí),最簡(jiǎn)單的方法是自己模擬 setTimeout
函數(shù),這樣,無(wú)論使用多少時(shí)間,您都可以調(diào)用該方法.
Basically, I think you are attempting to use fakeAsync
and tick
in ways for which they were not intended to be used. If you need to test a timeout the way that you have proposed, the simplest way would be to mock the setTimeout
function yourself so that, regardless of the time used, you can just call the method.
已編輯我遇到了一個(gè)相關(guān)的問(wèn)題,我想清除計(jì)時(shí)器,因?yàn)樗皇潜粶y(cè)試的部分,所以我不在乎花了多長(zhǎng)時(shí)間.我試過(guò)了:
EDITED I ran into a related issue where I wanted to clear the timers, and since it was not the part under test, I didn't care how long it took. I tried:
tick(Infinity);
這很有效,但是超級(jí)hacky.我最終選擇了
Which worked, but was super hacky. I ended up going with
discardPeriodicTasks();
我所有的計(jì)時(shí)器都被清除了.
And all of my timers were cleared.
這篇關(guān)于Angular 2 fakeAsync 在使用tick()的函數(shù)中等待超時(shí)?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!