【问题标题】:Unit testing interceptor with custom header带有自定义标头的单元测试拦截器
【发布时间】:2019-03-20 05:41:24
【问题描述】:

我一直在尝试在 Angular 6 的拦截器中运行一个测试单元,但是经过多次试验和错误后,我不断收到以下错误:

错误:应有一个对条件“按功能匹配:”的匹配请求,但没有找到。

我对 NG6 和单元测试有点陌生,在文档中找不到任何内容

这是我得到的:

令牌服务(由于与后端没有联系,因此被嘲笑)

export class TokenService {

token: EventEmitter<any> = new EventEmitter();

findTokenData(): Observable<any> {

    return Observable.create((observer: Observer<object>) => {
        observer.next({ headerName: x-fake, token: fake' });
        observer.complete();
    });
  }
}

休息拦截器

export class RestInterceptor implements HttpInterceptor {

constructor(public tokenService: TokenService) { }

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

    console.log('request intercepted...');

    let authReq: HttpRequest<any>;
    const customHeadersMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];

    // If the requested method is different GET or HEAD request the CSRF token from the service and add it to the headers
    if (customHeadersMethods.indexOf(req.method) !== -1) {
        this.tokenService.findTokenData().subscribe(res => {
            authReq = req.clone({
                headers: req.headers.set(res.headerName, res.token),
            });
        });

    } else {
        authReq = req.clone();
    }

    // send the newly created request
    return next.handle(authReq);
  }
}

休息拦截器规范

describe('RestInterceptor', () => {
const mockTokenService = {
  headerName: 'x-fake',
  token: 'fake'
};

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

  afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => {
    httpMock.verify();
}));

  it('Should add a custom header', inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {

http.post('/data', {}).subscribe(
  response => {
    expect(response).toBeTruthy();
  }
);

const req = httpMock.expectOne(r =>
  r.headers.has(`${mockTokenService.headerName}`) && 
  r.headers.get(`${mockTokenService.headerName}`) === `${mockTokenService.token}`);

expect(req.request.method).toEqual('POST');   

httpMock.verify();
}));
});

谁能帮我理解我错过了什么?

【问题讨论】:

    标签: javascript angular unit-testing jasmine angular-http-interceptors


    【解决方案1】:

    我认为您错过了这样一个事实,即TokenService 不是简单的值,而是带有返回 Observable 的 findTokenData 方法的类。

    会发生什么:

    你定义了模拟:

    const mockTokenService = {
      headerName: 'x-fake',
      token: 'fake'
    };
    

    覆盖它:

    {
      provide: TokenService,
      useValue: mockTokenService
    },
    

    现在 Angular 将使用这个 mockTokenService 对象作为注入到 RestInterceptor 中的值...

    this.tokenService.findTokenData().subscribe(res => {
                          ||
                      undefined  => error
    

    所以你可以采取以下措施来解决这个问题:

    import { of } from 'rxjs';
    ...
    const mockToken = {
      headerName: 'x-fake',
      token: 'fake'
    };
    const mockTokenService = {
      findTokenData: () => {
        return of(mockToken);
      }
    };
    ...
    const req = httpMock.expectOne(r =>
      r.headers.has(`${mockToken.headerName}`) &&
      r.headers.get(`${mockToken.headerName}`) === `${mockToken.token}`);
    

    【讨论】:

    • 这正是我所缺少的,也感谢您提供有关该问题的解释。
    • 很好的解释@yurzui。像这样解释的答案真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 2019-06-29
    • 2019-05-30
    相关资源
    最近更新 更多