Angular单元TESING HTTP截距附加XCSRF代币中的HTTP
我是单位测试全局HTTP拦截器,该全局从服务调用获得XSCRF令牌 getReponse(),并仅在帖子请求请求 postresponse() call(服务呼叫)中附加到标题 到目前为止,
我尝试测试它,但我无法通过测试案例。任何帮助都将不胜感激。
这是 optout.service.ts 文件,其中包含两种方法
getResponse()方法使用Mergemap链接两个呼叫,第一个服务呼叫是获取XCSRF的令牌,第二个呼叫是获得表单响应
的第二个呼叫
getReponse():Observable<optout>{
return this.httpClient.get<any>(`https://thisIsGetTokenApi.com`).pipe(
mergeMap(token=>this.httpClient.get<optout>(`https://someurlenpoint2.com`))
)
postResponse(data:optout):Observable<optout>{
return this.httpClient.post<optout>('https://api-endpoint',data)
}
在此处获得表单响应的标记是 global-http-interceptor.ts 文件
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Observable } from "rxjs";
import { tap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class GlobalHttpInterceptorService implements HttpInterceptor {
public hostURL=environment.hostURL;
public apiURL=environment.apiURL;
constructor(public router: Router) { }
token:string='';
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(this.token && req.method== "POST"){
req=req.clone({headers:req.headers.append('X-CSRF-TOKEN',this.token)});
}
return next.handle(req)
.pipe(
tap(event => {
if (event instanceof HttpResponse) {
if(req.url.includes('/getToken')){
this.token=event.body.XCSRFTOKEN;
}
}
}, (error:any) => {
if(error instanceof HttpErrorResponse){
if(error.status === 400 || error.status === 401 || error.status === 402){
window.location.href=`https://some-direct-url.com`;
}
}
})
)
}
}
这是我尝试的
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { GlobalHttpInterceptorService } from './global-http-interceptor.service';
import { RouterTestingModule } from '@angular/router/testing';
import { OptoutService } from './optout.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { API_CONFIG_TOKEN } from '../token';
import { GlobalConstants } from '../global-constants';
import { environment } from 'src/environments/environment';
import { optout } from '../model/optoutModel';
describe('GlobalHttpInterceptorService', () => {
let apiURL=environment.apiURL;
let httpController: HttpTestingController;
let getPreferenceApi='http://somegetrequestapi/v1/get';
let updatePreferenceApi='http://getpostrequest/v1/post';
let service: GlobalHttpInterceptorService;
let optoutService: OptoutService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports:[RouterTestingModule, HttpClientTestingModule ],
providers:[
OptoutService,
{provide:HTTP_INTERCEPTORS,useClass:GlobalHttpInterceptorService,multi:true},
{provide:API_CONFIG_TOKEN,useValue:{useFcvApi:false}},
]
});
service = TestBed.inject(GlobalHttpInterceptorService);
optoutService =TestBed.inject(OptoutService);
httpMock=TestBed.get(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should add an XCSRF header',() => {
const optoutMock:optout={
"output": {
"somevar1": "somvalue",
"somevar2": false
},{
"somevar1": "somvalue2",
"somevar2": false
}
}
optoutService.getResponse().subscribe(res=>{
expect(res).toBeTruthy();
})
optoutService.postResponse(optoutMock).subscribe(res=>{
expect(res).toBeTruthy();
})
const httpRequest=httpMock.expectOne(getTokenApi);
expect(httpRequest.request.headers.has('X-CSRF-TOKEN')).toEqual(true);
});
});
I am unit testing global HTTP interceptor that gets the XSCRF token from a service call getReponse() and appends it to the header only in POSTS request postResponse() call ( service call mentioned below )
So far I tried testing it but i am not able to pass the test case. Any help would be much appreciated.
This is the optout.service.ts file which contains two methods
getResponse() method uses mergeMap to chain two calls, first service call is to get the token for XCSRF and the second to get the form response
getReponse():Observable<optout>{
return this.httpClient.get<any>(`https://thisIsGetTokenApi.com`).pipe(
mergeMap(token=>this.httpClient.get<optout>(`https://someurlenpoint2.com`))
)
postResponse(data:optout):Observable<optout>{
return this.httpClient.post<optout>('https://api-endpoint',data)
}
Here is global-http-interceptor.ts file
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Observable } from "rxjs";
import { tap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class GlobalHttpInterceptorService implements HttpInterceptor {
public hostURL=environment.hostURL;
public apiURL=environment.apiURL;
constructor(public router: Router) { }
token:string='';
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(this.token && req.method== "POST"){
req=req.clone({headers:req.headers.append('X-CSRF-TOKEN',this.token)});
}
return next.handle(req)
.pipe(
tap(event => {
if (event instanceof HttpResponse) {
if(req.url.includes('/getToken')){
this.token=event.body.XCSRFTOKEN;
}
}
}, (error:any) => {
if(error instanceof HttpErrorResponse){
if(error.status === 400 || error.status === 401 || error.status === 402){
window.location.href=`https://some-direct-url.com`;
}
}
})
)
}
}
This is test spec file global-http-interceptor.spec.ts that i tried
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { GlobalHttpInterceptorService } from './global-http-interceptor.service';
import { RouterTestingModule } from '@angular/router/testing';
import { OptoutService } from './optout.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { API_CONFIG_TOKEN } from '../token';
import { GlobalConstants } from '../global-constants';
import { environment } from 'src/environments/environment';
import { optout } from '../model/optoutModel';
describe('GlobalHttpInterceptorService', () => {
let apiURL=environment.apiURL;
let httpController: HttpTestingController;
let getPreferenceApi='http://somegetrequestapi/v1/get';
let updatePreferenceApi='http://getpostrequest/v1/post';
let service: GlobalHttpInterceptorService;
let optoutService: OptoutService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports:[RouterTestingModule, HttpClientTestingModule ],
providers:[
OptoutService,
{provide:HTTP_INTERCEPTORS,useClass:GlobalHttpInterceptorService,multi:true},
{provide:API_CONFIG_TOKEN,useValue:{useFcvApi:false}},
]
});
service = TestBed.inject(GlobalHttpInterceptorService);
optoutService =TestBed.inject(OptoutService);
httpMock=TestBed.get(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should add an XCSRF header',() => {
const optoutMock:optout={
"output": {
"somevar1": "somvalue",
"somevar2": false
},{
"somevar1": "somvalue2",
"somevar2": false
}
}
optoutService.getResponse().subscribe(res=>{
expect(res).toBeTruthy();
})
optoutService.postResponse(optoutMock).subscribe(res=>{
expect(res).toBeTruthy();
})
const httpRequest=httpMock.expectOne(getTokenApi);
expect(httpRequest.request.headers.has('X-CSRF-TOKEN')).toEqual(true);
});
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

可能是因为
this.token
是虚假的(不是真实的),是否会被阻止。如果是这样,请尝试设置它,看看测试是否通过:
Could it be that the addition of the token is being blocked because
this.token
is falsy (not truthy)?If so, try setting it and see if the test passes: