简体   繁体   English

单元测试角度中的授权标头拦截器不起作用

[英]Unit testing Authorization header interceptor in angular not working

error: Expected one matching request for criteria "Match by function: ", found none. 错误:期望对标准“按功能匹配:”的一个匹配请求,但未找到。 I searched for many things and tried a few solutions. 我搜索了很多东西,并尝试了一些解决方案。 But none of them worked. 但是他们都不起作用。 This is my first project for unit testing. 这是我的第一个单元测试项目。 Here's my code. 这是我的代码。

Auth Interceptor 身份验证拦截器

export const API_URL = new InjectionToken<string>('apiUrl');
export class JwtInterceptor implements HttpInterceptor {
  constructor(@Inject(API_URL) private apiUrl: string) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

request = request.clone({url: this.prepareUrl(request.url)});

let authToken = localStorage.getItem('auth_token');
if (authToken) {
  request = request.clone({
    setHeaders: {
      Authorization: `Bearer ${authToken}`
    }
  });
}
else {
  // use proxy url for cors error
  request = request.clone({url: this.prepareUrl('https://cors-anywhere.herokuapp.com/' + request.url)});
  // Encode the String
  let encodedString = btoa(`${environment.clientId}:${environment.clientSecret}`);
  request = request.clone({
    setHeaders: {
      Authorization: `Basic ${encodedString}`
    }
  });
}
return next.handle(request);

}

  private isAbsoluteUrl(url: string): boolean {
    const absolutePattern = /^https?:\/\//i;
    return absolutePattern.test(url);
  }

  private prepareUrl(url: string): string {
    url = this.isAbsoluteUrl(url) ? url : this.apiUrl + '/' + url;
    return url.replace(/([^:]\/)\/+/g, '$1');
  }

}

Auth Interceptor Spec 验证拦截器规范

describe('Jwt Interceptor', ()=> { 

let httpTestingController: HttpTestingController;
  let http: HttpClient;      

  beforeEach(()=> {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [{
          provide: HTTP_INTERCEPTORS,
          useClass: JwtInterceptor,
          multi: true
        }]
    });

httpTestingController = TestBed.get(HttpTestingController);
http = TestBed.get(HttpClient);
 });

  it('should add Authorization header in each request', ()=> {
http.get('/data').subscribe(response => {
  expect(response).toBeTruthy();
});

const req = httpTestingController.expectOne(
  req => req.headers.has('Authorization')
);
expect(req.request.headers.has('Authorization')).toEqual(true);
expect(req.request.method).toEqual('GET');

req.flush({hello: 'world'});
 });    
  afterEach(()=> {
    httpTestingController.verify();
  });    
});

I also tried by setting authorization headers using mock service. 我还尝试通过使用模拟服务设置授权标头。 Can anyone help me what I am missing here? 谁能帮我我在这里想念的东西吗?

Finally, I found a solution and here is my final code for auth interceptor testing. 最后,我找到了一个解决方案,这是我进行身份验证拦截器测试的最终代码。 Use any of your service methods to make http request. 使用任何服务方法来发出http请求。 Thus, it can verify interceptor properly. 因此,它可以正确地验证拦截器。 Moreover, I also forgot to provide apiUrl in the TestBed configuration. 而且,我也忘记了在TestBed配置中提供apiUrl。

import {TestBed} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {HTTP_INTERCEPTORS, HttpClient} from '@angular/common/http';
import {API_URL, JwtInterceptor} from './jwt.interceptor';
import {DataService} from './data.service';

describe('JwtInterceptor', () => {
  let httpClient: HttpClient;
  let httpTestingController: HttpTestingController;
  let service: DataService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        DataService,
        {
          provide: HTTP_INTERCEPTORS,
          useClass: JwtInterceptor,
          multi: true
        },
        {
          provide: API_URL,
          useValue: {apiUrl: 'localhost'}
        }]
    });
    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
    service = TestBed.get(DataService);
// for localstorage mocking
let store = {};
const mockLocalStorage = {
  getItem: (key: string): string => {
    return key in store ? store[key] : null;
  },
  setItem: (key: string, value: string) => {
    store[key] = `${value}`;
  },
  removeItem: (key: string) => {
    delete store[key];
  },
  clear: () => {
    store = {};
  }
};
spyOn(localStorage, 'getItem').and.callFake(mockLocalStorage.getItem);
spyOn(localStorage, 'setItem').and.callFake(mockLocalStorage.setItem);
spyOn(localStorage, 'removeItem').and.callFake(mockLocalStorage.removeItem);
spyOn(localStorage, 'clear').and.callFake(mockLocalStorage.clear);
});



  afterEach(() => {
    httpTestingController.verify();
  });



  describe('making http calls', () => {
    it('adds authorization header', () => {
      const apiUrl = TestBed.get(API_URL);
      service.getData().subscribe(response => {
        expect(response).toBeTruthy();
      });

  localStorage.setItem('auth_token', 'any auth token here');
  const authToken = localStorage.getItem('auth_token');
  const req = httpTestingController.expectOne(apiUrl + '/getData');
  expect(req.request.headers.has('Authorization')).toEqual(true);
  expect(req.request.headers.get('Authorization')).toEqual(`Bearer ${authToken}`);
  });
 });

});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM