Reputation: 2986
this is the first project where I'm trying to have unit test working for angular, so I'm just figuring out how this exactly works. the project is in angular 7 and I have an HttpInteceptorService to retry 2 extra times if an HTTP request fails:
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
constructor() { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
return next.handle(request).pipe(retry(2));
}
}
my tests for this interceptor so far:
describe('HttpInterceptorService', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
providers: [
HttpInterceptorService,
{
provide: HTTP_INTERCEPTORS,
useClass: HttpInterceptorService,
multi: true
}
]
}));
it('should be created', () => {
const service: HttpInterceptorService = TestBed.get(HttpInterceptorService);
expect(service).toBeTruthy();
});
it('should get http 404', () => {
const http: HttpClient = TestBed.get(HttpClient);
http.get('/fake-route').subscribe((response: any) => {
expect(response).toBeTruthy();
expect(response.status).toEqual('404');
});
});
});
so I'm testing if i get a 404 successfully but I have no idea how to test if the interceptor is repeating the 2 extra times.
Edit
Actualy I was wrong, not even my 'should get http 404'
test is working correctly, it's just always giving a false positive.
Edit 2
I believe I'm getting closer, the 404 is now working properly and I've added a test for the "retrying" but it's still not working as expected I think the interceptor is probably not even being called...
it('should repeat failed request 2 more times', () => {
const emsg = 'deliberate 404 error';
jasmine.clock().install();
spyOn(httpClient, 'get').and.callThrough();
expect(httpClient.get).not.toHaveBeenCalled();
httpClient.get(fakeUrl).subscribe(
(response) => {
fail('should have failed with the 404 error');
},
(error) => {
expect(error.status).toEqual(404, 'status');
expect(error.error).toEqual(emsg, 'message');
});
jasmine.clock().tick(3000);
expect(httpClient.get).toHaveBeenCalledTimes(3);
jasmine.clock().uninstall();
});
and this test fails with "Expected spy get to have been called 3 times. It was called 1 times"
Upvotes: 2
Views: 1358
Reputation: 2986
OK, finally figured it out, my latest approach (Edit 2) was not the right one either. Here's my final and working test for the repeating:
it('should handle 404 with retry (2 times)', () => {
const emsg = 'deliberate 404 error';
httpClient.get(fakeUrl).subscribe(
(response) => {
fail('should have failed with the 404 error');
},
(error: HttpErrorResponse) => {
expect(error.status).toEqual(404, 'status');
expect(error.error).toEqual(emsg, 'message');
});
const retry = 2;
for (let i = 0, c = retry + 1; i < c; i++) {
const req = httpTestingController.expectOne(fakeUrl);
req.flush(emsg, { status: 404, statusText: 'Not Found' });
}
});
also added an assert to run after every test to make sure that there are no more pending requests:
afterEach(() => {
httpTestingController.verify();
});
Upvotes: 3