Angular单元TESING HTTP截距附加XCSRF代币中的HTTP

发布于 01-22 13:03 字数 4418 浏览 5 评论 0原文

我是单位测试全局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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叹倦2025-01-29 13:03:36

可能是因为this.token是虚假的(不是真实的),是否会被阻止。

// this token right here
if(this.token && req.method== "POST"){
      req=req.clone({headers:req.headers.append('X-CSRF-TOKEN',this.token)});
    }

如果是这样,请尝试设置它,看看测试是否通过:

service.token = 'abc';
optoutService.postResponse(optoutMock).subscribe(res=>{
      expect(res).toBeTruthy();
    })

    const httpRequest=httpMock.expectOne(getTokenApi);
    expect(httpRequest.request.headers.has('X-CSRF-TOKEN')).toEqual(true);

Could it be that the addition of the token is being blocked because this.token is falsy (not truthy)?

// this token right here
if(this.token && req.method== "POST"){
      req=req.clone({headers:req.headers.append('X-CSRF-TOKEN',this.token)});
    }

If so, try setting it and see if the test passes:

service.token = 'abc';
optoutService.postResponse(optoutMock).subscribe(res=>{
      expect(res).toBeTruthy();
    })

    const httpRequest=httpMock.expectOne(getTokenApi);
    expect(httpRequest.request.headers.has('X-CSRF-TOKEN')).toEqual(true);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文