Reputation: 2543
Here is a simple post function, I am able to unit test success and catchError in jasmine. Is it possible to test the finalize in jasmine? i.e in finalize, can we expect loader to be closed or not?
post(url,requestData){
this.http.post(url, requestData).pipe(
response => this.Response(response),
catchError((error: Response) => this.Error(error, msg)),
finalize(() => {
loader.close();
})
}
In finalize I am closing loader. I need to unit test the close loader to be called in finalize.
Upvotes: 1
Views: 1510
Reputation: 73
I had a case where I wanted to ensure that a "remove loading indicator" method was called from a finalize block of an Observable. The service is a home-grown one and not HTTP, but it's returning an observable so hopefully you can adapt it. The keys that I found are: 1) The test has to run in a fakeAsync() block. 2) I had to call next on the (mocked) subscription. 3) I then had to call complete() on the observable.
So, my solution was basically:
it ("should do something in finalize", () => {
let fakeResult = new Subject<any>();
// the "stop" method is called in the finalize of the Observable returned from testMethod()
spyOn(loadingService, "stop");
spyOn(service, "testMethod").andReturn(fakeResult);
component.methodUnderTestThatCallsServiceTestMethod(); // Observable returned here
fakeResult.next("whatever"); // Observable subscription fired here
tick();
fakeResult.complete(); // Observable finalize triggered here
expect(loadingService.stop).toHaveBeenCalled();
});
Upvotes: 1
Reputation: 11
I've struggling with the same problem. In my case i was trying to test the interceptor in Angular.
My solution was pass a real Observable as mock.
This is my actual code:
@Injectable()
export class SetLoadingService implements HttpInterceptor {
constructor(@Inject('INotificationLoading') private _INotificationLoading: INotificationLoading) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.headers.has('HideLoading')) {
return next.handle(req);
} else {
this._INotificationLoading.openLoading();
return next.handle(req).pipe(finalize(() => {
this._INotificationLoading.closeLoading();
}));
}
}
}
And this is my test:
it('should be show loading', () => {
const next: any = {
handle: () => {
return Observable.create(subscriber => {
subscriber.complete();
});
}
};
const requestMock = new HttpRequest('GET', '/test');
const closeLoadingSpy = spyOn<INotificationLoading>(notification, 'closeLoading');
service.intercept(requestMock, next).subscribe(() => {
expect(closeLoadingSpy).toHaveBeenCalled();
});
expect(openLoadingSpy).toHaveBeenCalled();
});
In a nutshell i solve the problem passing a Observable.create() as the return of the method handle. In your case you can set the return of http mock an Observable and set the expectation you need to check the test.
Upvotes: 1