У моих HTTP-перехватчиков действительно странная проблема, с которой я действительно не могу справиться. Точнее, при изменении ErrorEvent
на Error
и наоборот, оно охватывает одно из условий if / else, но делает другое условие не покрытым покрытием кода. Я использую Angular 9, Jest 24 и Rx JS 6.
http-error.interceptor.ts
import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
let errorMessage: string;
return next.handle(request).pipe(
catchError((err: HttpErrorResponse) => {
if (err.error instanceof ErrorEvent) {
// Client-side error.
errorMessage = `An error occurred: ${err.error.message}`;
alert('Network error.');
} else {
// Server-side error.
alert('Server unavailable.');
errorMessage = `Backend returned code ${err.status}, body was: ${err.error}`;
}
return throwError(errorMessage);
})
);
}
}
С этой настройкой, приведенный ниже тест проходит без учета части else
.
http-error.interceptor.spe c .ts
import { TestBed } from '@angular/core/testing';
import { HttpErrorInterceptor } from './http-error.interceptor';
import {
HttpClientTestingModule,
HttpTestingController
} from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { RegisterService } from './register.service';
describe('HttpErrorInterceptor', () => {
let httpErrorInterceptor: HttpErrorInterceptor;
let httpTestingController: HttpTestingController;
let registerService: RegisterService;
beforeEach(async () =>
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
RegisterService,
{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true
}
]
})
);
beforeEach(() => {
httpErrorInterceptor = new HttpErrorInterceptor();
httpTestingController = TestBed.inject(HttpTestingController);
registerService = TestBed.inject(RegisterService);
});
it('should catch errors when calling fake URL', async () => {
const fakeURL = 'https://fakeapi.com';
const fakeDataToBeSend = {
firstName: 'Daniel',
lastName: 'Danielecki',
email: 'daniel.danielecki@foo.com'
};
jest.spyOn(window, 'alert').mockImplementation(() => {}); // Note: window.alert = jest.fn() works too, but it contaminates other tests, therefore try to avoid it.
// Make an HTTP POST request
await registerService.registerUser(fakeDataToBeSend, fakeURL).subscribe(); // https://github.com/angular/angular/issues/18345 ????
httpTestingController
.expectOne(fakeURL)
.error(new ErrorEvent('Network error.')); //Error type instance can't be passed.
expect(window.alert).toHaveBeenCalledWith('Network error.');
// httpTestingController
// .expectOne(fakeURL)
// .error(new ErrorEvent('Server unavailable.')); //Error type instance can't be passed.
// expect(window.alert).toHaveBeenCalledWith('Server unavailable.');
});
Теперь в http-error.interceptor.ts Я изменяю ErrorEvent
на Error
и тест не пройден. Однако, если в http-error.interceptor.spe c .ts я внесу изменения, как показано ниже, тест проходит успешно. Но if
не покрывается, однако else
есть.
// httpTestingController
// .expectOne(fakeURL)
// .error(new ErrorEvent('Network error.')); //Error type instance can't be passed.
// expect(window.alert).toHaveBeenCalledWith('Network error.');
httpTestingController
.expectOne(fakeURL)
.error(new ErrorEvent('Server unavailable.')); //Error type instance can't be passed.
expect(window.alert).toHaveBeenCalledWith('Server unavailable.')