httpinterceptor测试失败

时间:2018-09-25 20:40:43

标签: angular unit-testing jasmine angular6

我正在使用Angular 6,我正在编写一个单元测试来测试HTTP请求何时收到不是401404的错误。

在因果运行程序中调试测试时,由于测试设置的原因,我可以得到一行this.router.navigate(['/genericErrorPage'])来执行的代码,但是我无法通过测试,我不确定为什么测试失败,因为在测试执行期间实际上调用了router.navigate()。

我尝试监视测试中的router对象和测试中的mockRouter对象,但都没有导致测试通过。使用任何一个间谍时,我都会收到“失败:预期的间谍导航已被调用。”

export class ErrorInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
  catchError(err => {
    if (err.status !== 404 || err.status !== 401) {
      this.router.navigate(['/genericErrorPage']);
    }
    const error = err.statusText;
    return throwError(error);
  })
);

} }

fdescribe('ErrorInterceptor', () => {
  class MockRouter {
  navigate = function() {};
}
let router: Router;
let interceptor: ErrorInterceptor;
const mockRouter: MockRouter = new MockRouter();

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

router = TestBed.get(Router);
interceptor = new ErrorInterceptor(router);
});

fit('should use router to navigate to error page on error', done => {
  spyOn(router, 'navigate');
   expect((interceptor as any) instanceof ErrorInterceptor).toBeTruthy();
  const next: any = {
    handle: (request: HttpRequest<any>) => {
    expect(router.navigate).toHaveBeenCalled();
    return Observable.create({ hello: 'world' });
  }
 };
   const req = new HttpRequest<any>('GET', 'http://localhost/any/api');
   interceptor.intercept(req, next).subscribe(obj => done());
  });
});

1 个答案:

答案 0 :(得分:0)

这就是我最终要做的事情:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from 
'@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
   constructor(private router: Router) {}

   intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     return next.handle(request).pipe(
        catchError(err => {
          if (err.status === 401) {
          }
          if (err.status === 404) {
          } else {
              this.router.navigate(['/genericErrorPage']);
          }

         return throwError(err);
        })
      );
     }
    }


import { ErrorInterceptor } from './error-interceptor';
import { Router } from '@angular/router';
import { mock } from 'ts-mockito/lib/ts-mockito';

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { EmployeeHomeService } from '../../services/employee/employee-home/employee-home.service';
import { USER_PROFILE_API_LOCATION } from '../../constants';

describe('ErrorInterceptor', () => {
   class MockRouter {
    navigate = function() {};
   }
  let employeeHomeService: EmployeeHomeService; //still need to make this generic/mock in case the EmployeeHomeService changes
  let httpMock: HttpTestingController;
  let mockRouter: MockRouter;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
       providers: [
        EmployeeHomeService,
        {
           provide: HTTP_INTERCEPTORS,
           useClass: ErrorInterceptor,
           multi: true
        },
         { provide: Router, useClass: MockRouter }
       ]
     });
    mockRouter = TestBed.get(Router);
    employeeHomeService = TestBed.get(EmployeeHomeService);
    httpMock = TestBed.get(HttpTestingController);
   });

  it('should have router redirect to error page on HTTP 500', done => {
    spyOn(mockRouter, 'navigate');
    employeeHomeService.retrieveEmployee().subscribe(
      res => {
        expect(false).toEqual(true); //should not hit here, but if it does, test will fail
        done();
      },
      err => {
     expect(mockRouter.navigate).toHaveBeenCalledWith(['/genericErrorPage']);
         done();
      }
    );

    httpMock.expectOne(USER_PROFILE_API_LOCATION).error(new ErrorEvent('500 
error'), {
       status: 500
     });
     httpMock.verify();
   });
 });



 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import { Employee } from '../../../containers/employee/models/employee';
 import { USER_PROFILE_API_LOCATION } from '../../../constants';

 @Injectable({
   providedIn: 'root'
})
 export class EmployeeHomeService {
   constructor(private http: HttpClient) {}

  retrieveEmployee(): Observable<Employee> {
    return this.http.get<Employee>(USER_PROFILE_API_LOCATION);
  }
 }