Angular 11:单元测试 HttpInterceptor - 无法让 catchError 在测试中工作
Angular 11: Unit testing an HttpInterceptor - can't get catchError to work in test
我正在努力完成我的 HttpInterceptor 的单元测试。拦截器用作全局错误处理程序,只需在 catchError(httpResponseError) 上触发。拦截器在我的网站上工作得很好,但我无法进行单元测试来实际测试代码。
这是拦截器的代码:
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { retry, tap, catchError } from 'rxjs/operators';
import { HttpServiceError } from '../models/httpServiceError.model';
import { LoggingService, LogLevel } from '../services/logging.service';
@Injectable({
providedIn: 'root'
})
export class HttpResponseInterceptorService implements HttpInterceptor{
public logLevel!: LogLevel;
constructor(private readonly loggingService: LoggingService) {
// Intentionally left blank
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
retry(1),
tap(() => console.log('ResponseInterceptor called')),
catchError((error:HttpErrorResponse) => {
console.log('HttpErrorResponse caught')
this.handleHttpError(error);
return throwError(error);
}))
}
private handleHttpError(error: HttpErrorResponse): Observable<HttpServiceError> {
const requestError = new HttpServiceError();
console.log('Error:', error);
console.log('handleHttpError function called');
requestError.errorNumber = error.status;
requestError.statusMessage = error.statusText;
switch (error.status) {
case 401: {
requestError.friendlyMessage = 'You are not logged in';
break;
}
case 403: {
requestError.friendlyMessage = 'You are not logged in';
break;
}
case 404: {
requestError.friendlyMessage = 'The service failed to respond';
break;
}
case 429: {
requestError.friendlyMessage = 'The service is busy';
break;
}
case 500: {
requestError.friendlyMessage = 'The service is not responding correctly';
break;
}
default: {
requestError.friendlyMessage = 'An error occured retrieving the data';
break;
}
}
this.loggingService.logWithLevel(JSON.stringify(requestError), LogLevel.Information);
return throwError(requestError);
}
}
如您所见,我有几个控制台,其中有日志,只有第一个是测试中的触发器。
这是我的规范文件:
import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpRequest, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { fakeAsync, inject, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
import { LoggingService } from '../services/logging.service';
import { HttpResponseInterceptorService } from './httpresponseinterceptor.service';
describe('HttpResponseInterceptorService', () => {
let interceptor: HttpResponseInterceptorService;
let httpMock: HttpTestingController;
let loggingService: LoggingService;
let httpClient: HttpClient;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpResponseInterceptorService,
multi: true,
},
]
});
loggingService = TestBed.inject(LoggingService);
interceptor = TestBed.inject(HttpResponseInterceptorService);
httpMock = TestBed.inject(HttpTestingController);
httpClient = TestBed.inject(HttpClient);
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
it('should call loggingService with a friendlyMessage of The service failed to respond (404)', fakeAsync(() => {
spyOn(loggingService,'logWithLevel');
const errorResponse = new HttpErrorResponse({
error: '404 error',
status: 404, statusText: 'Not Found'
});
httpClient.get('/api').subscribe();
let request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error'), errorResponse);
// request.flush('Request failed', {status:404, statusText:'Not Found'});
// request.flush(errorResponse);
expect(loggingService.logWithLevel).toHaveBeenCalled();
}));
});
我试过 request.error(new ErrorEvent('404 Error'), errorResponse);
和 // request.flush(errorResponse);
:None 实际上触发了 catchError((error:HttpErrorResponse)
代码分支。
非常欢迎好的想法和反馈!
谢谢,
比亚恩
我认为您的问题来自 'retry(1)'。
如果你想传入 catchError
函数,你必须调用 numberOfRetry + 1
次 api。
也许你可以试试:
let request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error first'), errorResponse);
request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error second'), errorResponse);
我正在努力完成我的 HttpInterceptor 的单元测试。拦截器用作全局错误处理程序,只需在 catchError(httpResponseError) 上触发。拦截器在我的网站上工作得很好,但我无法进行单元测试来实际测试代码。
这是拦截器的代码:
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { retry, tap, catchError } from 'rxjs/operators';
import { HttpServiceError } from '../models/httpServiceError.model';
import { LoggingService, LogLevel } from '../services/logging.service';
@Injectable({
providedIn: 'root'
})
export class HttpResponseInterceptorService implements HttpInterceptor{
public logLevel!: LogLevel;
constructor(private readonly loggingService: LoggingService) {
// Intentionally left blank
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
retry(1),
tap(() => console.log('ResponseInterceptor called')),
catchError((error:HttpErrorResponse) => {
console.log('HttpErrorResponse caught')
this.handleHttpError(error);
return throwError(error);
}))
}
private handleHttpError(error: HttpErrorResponse): Observable<HttpServiceError> {
const requestError = new HttpServiceError();
console.log('Error:', error);
console.log('handleHttpError function called');
requestError.errorNumber = error.status;
requestError.statusMessage = error.statusText;
switch (error.status) {
case 401: {
requestError.friendlyMessage = 'You are not logged in';
break;
}
case 403: {
requestError.friendlyMessage = 'You are not logged in';
break;
}
case 404: {
requestError.friendlyMessage = 'The service failed to respond';
break;
}
case 429: {
requestError.friendlyMessage = 'The service is busy';
break;
}
case 500: {
requestError.friendlyMessage = 'The service is not responding correctly';
break;
}
default: {
requestError.friendlyMessage = 'An error occured retrieving the data';
break;
}
}
this.loggingService.logWithLevel(JSON.stringify(requestError), LogLevel.Information);
return throwError(requestError);
}
}
如您所见,我有几个控制台,其中有日志,只有第一个是测试中的触发器。
这是我的规范文件:
import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpRequest, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { fakeAsync, inject, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
import { LoggingService } from '../services/logging.service';
import { HttpResponseInterceptorService } from './httpresponseinterceptor.service';
describe('HttpResponseInterceptorService', () => {
let interceptor: HttpResponseInterceptorService;
let httpMock: HttpTestingController;
let loggingService: LoggingService;
let httpClient: HttpClient;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpResponseInterceptorService,
multi: true,
},
]
});
loggingService = TestBed.inject(LoggingService);
interceptor = TestBed.inject(HttpResponseInterceptorService);
httpMock = TestBed.inject(HttpTestingController);
httpClient = TestBed.inject(HttpClient);
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
it('should call loggingService with a friendlyMessage of The service failed to respond (404)', fakeAsync(() => {
spyOn(loggingService,'logWithLevel');
const errorResponse = new HttpErrorResponse({
error: '404 error',
status: 404, statusText: 'Not Found'
});
httpClient.get('/api').subscribe();
let request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error'), errorResponse);
// request.flush('Request failed', {status:404, statusText:'Not Found'});
// request.flush(errorResponse);
expect(loggingService.logWithLevel).toHaveBeenCalled();
}));
});
我试过 request.error(new ErrorEvent('404 Error'), errorResponse);
和 // request.flush(errorResponse);
:None 实际上触发了 catchError((error:HttpErrorResponse)
代码分支。
非常欢迎好的想法和反馈!
谢谢, 比亚恩
我认为您的问题来自 'retry(1)'。
如果你想传入 catchError
函数,你必须调用 numberOfRetry + 1
次 api。
也许你可以试试:
let request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error first'), errorResponse);
request = httpMock.expectOne("/api");
request.error(new ErrorEvent('404 Error second'), errorResponse);