I want to test an HTTP call error response with the HttpClientTestingModule
. This works fine until I add a rxjs retry(2)
to the HTTP call. Then, the test obviously complains that an unexpected request is found:
Expected no open requests, found 1
But now, I don't know how to expect two requests using the HttpTestingController
:
@Injectable()
export class Service {
constructor(private http: HttpClient) { }
get() {
return this.http.get<any>('URL')
.pipe(
retry(2),
catchError(error => of(null))
)
}
}
describe('Service', () => {
let httpTestingController: HttpTestingController;
let service: Service;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [Service],
imports: [HttpClientTestingModule]
});
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(Service);
});
afterEach(() => {
httpTestingController.verify();
});
it('should handle 404 with retry', () => {
service.get().subscribe((data: any) => {
expect(data).toBe(null);
});
expectErrorResponse(404);
});
function expectErrorResponse(status: number) {
const requests = httpTestingController.match('URL');
// fails -> finds only one request
expect(requests.length).toBe(2);
requests.forEach(req => req.flush('error', {status, statusText: 'Not Found'}));
}
});
If I remove the expect(requests.length).toBe(2)
, the test will fail with the error message from before.
You can try it out with this Stackblitz
catch( (error: Response) => { return Observable. throw(error); } );
The fundamentals of Angular - HttpClient - retry() states:
The RxJS library offers several retry operators that are worth exploring. The simplest is called retry() and it automatically re-subscribes to a failed Observable a specified number of times. Re-subscribing to the result of an HttpClient method call has the effect of reissuing the HTTP request.
So every time you call flush it leaves behind an open request. You just need to repeat the request handling and flushing as many times as the service retries the request.
it('can test for 404 error', () => {
const emsg = 'deliberate 404 error';
testService.getData().subscribe(
data => fail('should have failed with the 404 error'),
(error: HttpErrorResponse) => {
expect(error.status).toEqual(404, 'status');
expect(error.error).toEqual(emsg, 'message');
}
);
const retryCount = 3;
for (var i = 0, c = retryCount + 1; i < c; i++) {
let req = httpTestingController.expectOne(testUrl);
req.flush(emsg, { status: 404, statusText: 'Not Found' });
}
});
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