Angular 10:使用HttpInterceptor进行单元测试,修改响应而不获取HttpResponse
如果到处搜索答案,到目前为止,我尝试过的每件事都会产生相同的缺失信息 这是运行Angular 10的最新版本的Karma/Jasmine 本质上,我有一个HTTP拦截器,它查看返回对象的内容类型。如果是json,继续正常操作,如果是html…然后抛出一个错误Angular 10:使用HttpInterceptor进行单元测试,修改响应而不获取HttpResponse,angular,unit-testing,karma-jasmine,angular-http-interceptors,angular-test,Angular,Unit Testing,Karma Jasmine,Angular Http Interceptors,Angular Test,如果到处搜索答案,到目前为止,我尝试过的每件事都会产生相同的缺失信息 这是运行Angular 10的最新版本的Karma/Jasmine 本质上,我有一个HTTP拦截器,它查看返回对象的内容类型。如果是json,继续正常操作,如果是html…然后抛出一个错误 import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { httpStatusCodes } from '../../../shared/enums/httpStatusCodes.enum';
import { errorResponse } from './../../../shared/models/errorResponse.model';
@Injectable()
export class WafErrorInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
map((event: HttpEvent<any>) => {
console.log(event instanceof HttpResponse);
if (
event instanceof HttpResponse &&
event.headers.has('content-type') &&
event.headers.get('content-type') === 'application/json'
) {
return event;
}
const throwErrorResponse = new errorResponse(
httpStatusCodes.WAF_ERROR,
'99999',
event instanceof HttpResponse
? event.body
: 'unknown error occurred'
);
throw throwErrorResponse;
})
);
}
}
导入{
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse
}来自“@angular/common/http”;
从“@angular/core”导入{Injectable};
从“rxjs”导入{Observable};
从“rxjs/operators”导入{map};
从“../../../shared/enums/httpStatusCodes.enum”导入{httpStatusCodes};
从“../../../../shared/models/errorResponse.model”导入{errorResponse};
@可注射()
导出类WafErrorInterceptor实现HttpInterceptor{
拦截(
请求:HttpRequest,
下一步:HttpHandler
):可见{
返回next.handle(request.pipe)(
映射((事件:HttpEvent)=>{
log(HttpResponse的事件实例);
如果(
HttpResponse的事件实例&&
event.headers.has('content-type')&&
event.headers.get('content-type')='application/json'
) {
返回事件;
}
const-throwErrorResponse=新的错误响应(
httpStatusCodes.WAF_错误,
'99999',
HttpResponse的事件实例
?事件主体
:“发生未知错误”
);
投掷反应;
})
);
}
}
然后在我的单元测试中,我运行以下命令:
import {
HttpClient,
HttpHeaders,
HttpResponse,
HTTP_INTERCEPTORS
} from '@angular/common/http';
import {
HttpClientTestingModule,
HttpTestingController
} from '@angular/common/http/testing';
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { errorResponse } from './../../../shared/models/errorResponse.model';
import { WafErrorInterceptor } from './waf-error.service';
describe('WafErrorInterceptor', () => {
let httpMock: HttpTestingController;
let httpClient: HttpClient;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: WafErrorInterceptor,
multi: true
}
]
});
httpMock = TestBed.get(HttpTestingController);
httpClient = TestBed.get(HttpClient);
});
afterEach(() => {
httpMock.verify();
});
it('intercept: when no error, then subscribe returns successfully', () => {
const testData: string = 'test';
httpClient.get<string>('https://secure.testurl.com/success').subscribe(
(data) => expect(data).toBeTruthy(),
(error: errorResponse) => {
console.log(error);
fail('error should not have been called');
}
);
tick();
let req = httpMock.expectOne('https://secure.testurl.com/success');
tick();
let httpHeaders = new HttpHeaders();
httpHeaders.set('content-type', 'application/json');
const expectedResponse = new HttpResponse<string>({
status: 200,
statusText: 'OK',
body: testData,
headers: httpHeaders
});
//req.flush(expectedResponse);
req.event(expectedResponse);
});
});
导入{
HttpClient,
HttpHeader,
HttpResponse,
HTTP_拦截器
}来自“@angular/common/http”;
进口{
HttpClientTestingModule,
HttpTestingController
}来自“@angular/common/http/testing”;
从'@angular/core/testing'导入{fakeAsync,TestBed,tick};
从“../../../../shared/models/errorResponse.model”导入{errorResponse};
从“./waf error.service”导入{WafErrorInterceptor};
描述('WafErrorInterceptor',()=>{
让httpock:HttpTestingController;
let-httpClient:httpClient;
在每个之前(()=>{
TestBed.configureTestingModule({
导入:[HttpClientTestingModule],
供应商:[
{
提供:HTTP_拦截器,
useClass:WafErrorInterceptor,
多:真的
}
]
});
httpMock=TestBed.get(HttpTestingController);
httpClient=TestBed.get(httpClient);
});
之后(()=>{
httpMock.verify();
});
它('截取:当没有错误时,订阅成功返回',()=>{
常量testData:string='test';
httpClient.get('https://secure.testurl.com/success)。订阅(
(数据)=>expect(数据).toBeTruthy(),
(错误:errorResponse)=>{
console.log(错误);
失败(“不应调用错误”);
}
);
勾选();
let req=httpMock.expectOne('https://secure.testurl.com/success');
勾选();
设httpHeaders=newHttpHeaders();
httpHeaders.set('content-type','application/json');
const expectedResponse=新的HttpResponse({
现状:200,
statusText:'确定',
正文:testData,
标题:httpHeaders
});
//要求冲洗(预期响应);
请求事件(预期响应);
});
});
我已经尝试过刷新,在这里我只发送回数据,在那里我发送回数据和标题/状态。我发回一个httpresponse,等等。每次,当它进入拦截器时,拦截器不会看到httpresponse类型的响应,并且console.log总是返回false
我甚至刚刚创建了一个单元测试,单元测试在其中发送一个模拟对象…甚至还有同样的问题
想法
更新:
下面的答案适用于Map,但在测试catchErrorInterceptor时仍然存在问题。代码在我的站点上运行。我们的API返回一个对象,其中错误包含一个错误数组。因此,我们抓住第一个并使用它
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
catchError((error: HttpErrorResponse) => {
let statusCode = httpStatusCodes.CONFLICT;
let errorMessage = '';
let errorCode = '99999';
statusCode =
error.status === 0
? httpStatusCodes.INTERNAL_SERVER_ERROR
: error.status;
if (error.error.errors && error.error.errors.length > 0) {
errorCode = error.error.errors[0].code;
errorMessage = error.error.errors[0].description;
} else {
errorMessage = error.message;
}
const throwErrorResponse = new errorResponse(
statusCode,
errorCode,
errorMessage
);
return throwError(throwErrorResponse);
})
);
}
}
@Injectable()
导出类ErrorInterceptor实现HttpInterceptor{
拦截(
请求:HttpRequest,
下一步:HttpHandler
):可见{
返回next.handle(request.pipe)(
catchError((错误:HttpErrorResponse)=>{
让statusCode=httpStatusCodes.CONFLICT;
让errorMessage='';
让errorCode='99999';
状态码=
错误。状态===0
?httpStatusCodes.INTERNAL\u服务器\u错误
:错误。状态;
if(error.error.errors&&error.error.errors.length>0){
errorCode=错误。错误。错误[0]。代码;
errorMessage=错误。错误。错误[0]。说明;
}否则{
errorMessage=error.message;
}
const-throwErrorResponse=新的错误响应(
状态码,
错误代码,
错误信息
);
返回投掷者(投掷者反应);
})
);
}
}
以下是其中一项测试:
it('intercept: when delibarate 409, then error returned', (done) => {
httpClient
.get<string>('https://secure.go2bank.com/error')
.pipe(skip(1))
.subscribe(
(data) => fail('should have failed with the 404 error'),
(error: errorResponse) => {
expect(error).toBeTruthy(); // check if executed
expect(error.httpStatusCodes).toBe(
httpStatusCodes.CONFLICT
);
expect(error.errorCode).toBe('1007');
expect(error.errorMessage).toBe(
'Validation error Authorization'
);
done();
}
);
const errorInitEvent: ErrorEventInit = {
message: null,
error: {
errors: [
{
code: '1007',
description: 'Validation error Authorization.',
message: null,
link: null,
additionalinfo: null
}
]
}),
lineno: null,
colno: null,
filename: null
};
let error = new ErrorEvent('ERROR', errorInitEvent);
httpMock.expectOne('https://secure.go2bank.com/error').error(error, {
status: httpStatusCodes.CONFLICT,
statusText: 'Conflict',
headers: new HttpHeaders().set('content-type', 'application/json')
});
});
it('intercept:when delibarate 409,然后返回错误',(done)=>{
httpClient
.get('https://secure.go2bank.com/error')
.管道(箕斗(1))
.订阅(
(数据)=>fail('404错误本应失败'),
(错误:errorResponse)=>{
import {
HttpEventType,
...
} from '@angular/common/http';
...
map((event: HttpEvent<any>) => {
if (event.type === HttpEventType.Sent) { <---------- add this
return event;
}
if (
event instanceof HttpResponse &&
event.headers.has('content-type') &&
event.headers.get('content-type') === 'application/json'
) {
return event;
}
...
flush(body, opts?: {
headers?: HttpHeaders | {
[name: string]: string | string[];
};
status?: number;
statusText?: string;
})
it('intercept: when no error, then subscribe returns successfully', () => {
const testData: string = 'test';
httpClient.get<string>('https://secure.testurl.com/success').subscribe(
(data) => expect(data).toBeTruthy(),
(error: errorResponse) => {
console.log(error);
fail('error should not have been called');
}
);
const req = httpMock.expectOne('https://secure.testurl.com/success');
req.flush(testData, {
status: 200,
statusText: 'OK',
headers: new HttpHeaders().set('content-type', 'application/json')
});
});