What is the difference between fakeAsync's tick() and done() in angular2 testing?
Those 2 things have nothing in common.
done
is just a callback to let your test runner know when an async operation is done.
For example:
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();
});
});
You might also use async
for that (just to avoid calling done
manually):
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
})
);
Now, fakeAsync
gives you control over time (which is really powerful) so you can write your tests in a synchronous way, and simulate that time goes by to avoid waiting for setTimeout
for example:
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
})
);
So just to be clear, with fakeAsync
in the last example, if the setTimeout was set on 10s, the test would still be executed instantly.
Sanju
A dab of programming, A spoonful of curiosity and a tumbler full of coffee make me, me.
Updated on July 28, 2022Comments
-
Sanju almost 2 years
I'm trying to figure out what differentiates fakeAsync's
tick()
method fromdone()
as suggested by some answers on stack overflow.Using
tick()
we can simulate a timeout, but can we accomplish the same usingdone()
?Why does angular consider it more viable method than using
async
orfakeAsync
?Take for example.
This method works for me...
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); });
But following method returns '
6 timer(s) still in queue
' error...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); }));
Note:
The data for array
names
is asynchronous since it's retrieved from back end using 'get' operation. But here i'm mocking the data.The data in array is iterated through and passed to another child component which displays it in the view.
-
Max Koretskyi over 6 yearsalso you can add that
done
is a native Jasmine method whileasync
andfakeAsync
are added by Angular testing framework -
maxime1992 over 6 yearsIndeed, you'll only be able to use
async
andfakeAsync
by importing them fromangular/core/testing
:) -
Sanju over 6 years@Maxime Great explanation! Thanks!
-
Sanju over 6 years@Maxime Can you give an instance, when each of these scenarios are preferred over others?
-
maxime1992 over 6 yearsI mostly use async over done callbacks. But I've read that it might be slowering tests down so not sure it's a good idea. About fakeAsync, it's really handy to avoid waiting and taking back control over time, that's just it :)
-
Sanju over 6 years@Maxime Thanks!
-
EugenSunic about 6 yearsWhere is tick() mentioned in all of this story?
-
maxime1992 about 6 yearsTick is nearly the same as flush. Flush will run all the asynchronous tasks in queue and tick will too if no arguments are provided. But you can also decide to pass a time in ms, and it'll run the tasks that are only supposed to be run during that time. So for example if you have to setTimeout, one at 2s and the other at 1, run tick(1000) and only the first callback will have been called.