I\'m trying to add unit tests to my Angular 2 app. In one of my components, there is a button with a (click) handler. When the user clicks the button a function
I had a similar problem (detailed explanation below), and I solved it (in jasmine-core: 2.52) by using the tick function with the same (or greater) amount of milliseconds as in original setTimeout call.
For example, if I had a setTimeout(() => {...}, 2500); (so it will trigger after 2500 ms), I would call tick(2500), and that would solve the problem.
What I had in my component, as a reaction on a Delete button click:
delete() {
this.myService.delete(this.id)
.subscribe(
response => {
this.message = 'Successfully deleted! Redirecting...';
setTimeout(() => {
this.router.navigate(['/home']);
}, 2500); // I wait for 2.5 seconds before redirect
});
}
Her is my working test:
it('should delete the entity', fakeAsync(() => {
component.id = 1; // preparations..
component.getEntity(); // this one loads up the entity to my component
tick(); // make sure that everything that is async is resolved/completed
expect(myService.getMyThing).toHaveBeenCalledWith(1);
// more expects here..
fixture.detectChanges();
tick();
fixture.detectChanges();
const deleteButton = fixture.debugElement.query(By.css('.btn-danger')).nativeElement;
deleteButton.click(); // I've clicked the button, and now the delete function is called...
tick(2501); // timeout for redirect is 2500 ms :) <-- solution
expect(myService.delete).toHaveBeenCalledWith(1);
// more expects here..
}));
P.S. Great explanation on fakeAsync and general asyncs in testing can be found here: a video on Testing strategies with Angular 2 - Julie Ralph, starting from 8:10, lasting 4 minutes :)