代码之家  ›  专栏  ›  技术社区  ›  Pritam Bohra

Spyon在Angular6的HTTP拦截器中不工作

  •  0
  • Pritam Bohra  · 技术社区  · 6 年前

    我正在尝试测试记录 http 请求。我有一个记录请求响应的日志服务。拦截器只为get请求者记录日志。

    这是我的拦截器:

    import { HttpInterceptor, HttpHandler, HttpEvent, HttpRequest, HttpResponse } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { tap } from 'rxjs/operators';
    import { LogService } from './log.service';
    import { Injectable } from '@angular/core';
    
    @Injectable({providedIn: 'root'})
    export class LoggerInterceptor implements HttpInterceptor {
    
      constructor(private _log: LogService) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req)
          .pipe(
            tap(event => {
              if (event instanceof HttpResponse) {
                if (req.method === 'GET') {
                  this._log.log('I was logged');
                }
              }
            })
          );
      }
    }
    

    这是规范文件:

    import { TestBed } from '@angular/core/testing';
    import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@angular/common/http/testing';
    import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
    import { HeaderInterceptor } from './add.header.interceptor';
    import { LogService } from './log.service';
    import { LoggerInterceptor } from './logger.interceptor';
    
    const posts: Array<any> = [
      {
        'userId': 1,
        'id': 1,
        'title': 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
        'body': 'quia et suscipit\nsuscipit recusandae consequuntur expedita et '
      },
      {
        'userId': 1,
        'id': 2,
        'title': 'qui est esse',
        'body': 'est rerum tempore vitae\nsequi sint nihil reprehenderit dolor b'
      }
    ];
    
    describe('HeaderInterceptor', () => {
    
      let httpMock: HttpTestingController;
      let logService: LogService;
      let httpClient: HttpClient;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          imports: [ HttpClientTestingModule ],
          providers: [
            LogService,
            { provide: HTTP_INTERCEPTORS, useClass: LoggerInterceptor, multi: true }
          ]
        });
    
        httpMock = TestBed.get(HttpTestingController);
        logService = TestBed.get(LogService);
        httpClient = TestBed.get(HttpClient);
      });
    
      it('must log the http get request', () => {
    
        const spy = spyOn(logService, 'log');
    
        httpClient.get('http://jsonplaceholder.typicode.com/posts')
          .subscribe(
            (data: Array<any>) => {
              expect(data.length).toBe(2);
            }
        );
    
        const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
        expect(req.request.headers.has('Content-Type')).toBe(true);
        expect(spy).toHaveBeenCalled();
    
        req.flush(posts);
      });
    
      it('must log the http post request', () => {
    
        const spy = spyOn(logService, 'log');
    
        httpClient.post('http://jsonplaceholder.typicode.com/posts', posts)
          .subscribe();
    
        const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
        expect(req.request.headers.has('Content-Type')).toBe(true);
        expect(spy).not.toHaveBeenCalled();
    
        req.flush(posts);
      });
    });
    

    我有头部感受器 Content-Type 每个http请求的头。对那个拦截器的测试没问题。

    当我试着测试航海截击机的时候,我发现了间谍的错误 expect(spy).toHaveBeenCalled();

    错误如下:

    Error: Expected spy log to have been called.
        at stack (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2455:17)
        at buildExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2425:14)
        at Spec.expectationResultFactory (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:901:18)
        at Spec.addExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:524:34)
        at Expectation.addExpectationResult (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:845:21)
        at Expectation.toHaveBeenCalled (http://localhost:9876/absolute/home/pritambohra/Desktop/testing-in-angular/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2369:12)
        at UserContext.<anonymous> (http://localhost:9876/src/app/logger.interceptor.spec.ts?:57:17)
        at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:388:1)
        at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:288:1)
        at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:387:1)
    

    我不太确定我错在哪里。为了代码覆盖率,我正在执行post-http调用。我需要修理什么?

    1 回复  |  直到 6 年前
        1
  •  0
  •   user776686    6 年前

    这可能只是部分答案。

    我不是测试专家,所以我不应该试图解释 为什么 你的代码失败了,但我相信下面的代码是正确的,并且做了正确的测试。

    imo在get案例中,您的代码有两个问题: -你在期待间谍之后脸红了-应该是相反的方向 -你不是在打电话 done() 从内 .subscribe()

    不过,post case的代码似乎工作正常(除了测试描述似乎不正确之外,难道不是应该改为“不应该记录”吗?)

    我漏掉了支票 Content-Type 头球因为某些原因失败了(没有时间进一步调查-会很好奇你是否解决了它),这不是你的问题的一部分。

    describe('Logger Interceptor', () => {
      let httpMock: HttpTestingController;
      let httpClient: HttpClient;
      let logService: LogService;
      let spy: Function;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          imports: [HttpClientTestingModule],
          providers: [
            {
              provide: HTTP_INTERCEPTORS,
              useClass: LoggerInterceptor,
              multi: true,
            },
          ],
        });
    
        httpClient = TestBed.get(HttpClient);
        httpMock = TestBed.get(HttpTestingController);
        logService = TestBed.get(LogService);
        spy = spyOn(logService, 'log');
      });
    
      afterEach(() => httpMock.verify());
    
      it('must log the http get request', (done) => {
    
        httpClient.get('http://jsonplaceholder.typicode.com/posts').subscribe((data: any[]) => {
          expect(data.length).toBe(2);
          done();
        });
    
        const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
    
        req.flush(posts);
        expect(spy).toHaveBeenCalled();
      });
    
      it('should NOT log the http post request', () => {
    
        httpClient.post('http://jsonplaceholder.typicode.com/posts', posts)
          .subscribe();
    
        const req: TestRequest = httpMock.expectOne('http://jsonplaceholder.typicode.com/posts');
        expect(spy).not.toHaveBeenCalled();
    
        req.flush(posts);
      });
    });
    

    如果有人能解释的话,我很想知道为什么GET案例需要进行上述更改。