我正在使用Angular 6,我正在编写一个单元测试来测试HTTP请求何时收到不是401
或404
的错误。
在因果运行程序中调试测试时,由于测试设置的原因,我可以得到一行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());
});
});
答案 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);
}
}