I'm trying to test an Angular 2 component which relies on a service call to populate the data. But, this service calls promise is handled inside another function.
this.data = null; //empty data is defined here.
public getDataMethod(){
// controller related logic
privateService.privateMethod(
(data) => {this.data = data} //the data is populated here
)
}
How can I wait for the inner function to resolve?
I read that we can wait for promises to resolve with 'done' but the only examples I found were of directly calling the promise. (Not a nested promise inside a function)
I tried passing the done
method into the function and it works well.
public getDataMethod(done){
// controller related logic
privateService.privateMethod(
(data) => {this.data = data} //the data is populated here
done(); //Calling done when the promise is resolved.
)
}
But, that does muddy up the code that's tested. Is there a better way of waiting for the data
value to populate before running the tests?
This is all explained in the Angular docs testing section Test a component with an async service. You basically have a couple options.
Use async
to wrap the tests. Angular knows when there are asynchronous tasks happening, because it uses zones to monkey patch all the asynchronous functions like setTimeout
. When we use async
, Angular will prevent the test from completing until all the async tasks are out of the queue.
import { async } from '@angular/core/testing';
it('..', async(() => {
// any async calls that happen between here
// will be completed before the test completes
}))
the other part to this is waiting for async tasks to complete before we make any assertions. For that, we can use fixture.whenStable()
which will wait before the async tasks to complete, then notify us with a promise
it('..', async(() => {
service.someAsyncTask();
fixture.whenStable().then(() => {
expect(...)
})
}))
The other option is to use fakeAsync/tick
combo. Angular allows us to wait for the async tasks to complete by calling tick
. This allows us to make the test seem synchronous
import { fakeAsync, tick } from '@angular/core/testing';
it('..', fakeAsync(() => {
service.someAsyncTask();
tick();
expect(...)
}))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With