我的HTTP拦截器确实有一个很奇怪的问题,我确实无法解决。更准确地说,将ErrorEvent
更改为Error
时,反之亦然,它涵盖了if / else条件之一,但使另一个条件未包括在代码覆盖范围内。我正在使用Angular 9,Jest 24和RxJS 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.spec.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.spec.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.')