I have already added RouterTestingModule
to my import for my unit test. But it is still throwing the following error.
The only difference is know is that my routing page is different from the norm.
I have attached my codes for reference.
What is it that i need to change? Or how do I test my interceptor using my router class?
Console:
NullInjectorError: StaticInjectorError(DynamicTestModule)[ErrorHandlerInterceptor -> Router]:
StaticInjectorError(Platform: core)[ErrorHandlerInterceptor -> Router]:
NullInjectorError: No provider for Router!
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'ErrorHandlerInterceptor', Function ] })
fatalerror-routing.module.ts:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { extract } from '@app/core';
import { FatalerrorComponent } from './fatalerror.component';
const routes: Routes = [
// Module is lazy loaded, see app-routing.module.ts
{ path: '', component: FatalerrorComponent, data: { title: extract('Fatal Error') } }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: []
})
export class FatalerrorRoutingModule {}
app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
import { Shell } from '@app/shell/shell.service';
const routes: Routes = [
Shell.childRoutes([{ path: 'fatalerror', loadChildren: './shared/fatalerror/fatalerror.module#FatalerrorModule' }]),
{ path: '**', redirectTo: '', pathMatch: 'full' }
];
@NgModule({
imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule {}
error-handler.interceptor.ts:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { environment } from '@env/environment';
import { Logger } from '../logger.service';
import { NotificationCenterService } from '@app/shared/notification-center.service';
import { Router } from '@angular/router';
/**
* Adds a default error handler to all requests.
*/
@Injectable({
providedIn: 'root'
})
export class ErrorHandlerInterceptor implements HttpInterceptor {
constructor(private noti: NotificationCenterService, private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => this.errorHandler(error)));
}
// Customize the default error handler here if needed
private errorHandler(error: HttpErrorResponse): Observable<HttpEvent<any>> {
const errorMsg = error.error.message || error.error || error.statusText;
if (error.status === undefined || error.status === null || error.status === 500 || error.status === 0) {
//redirect to error page
this.router.navigate(['fatalerror']);
} else {
//show in notification
this.noti.open(errorMsg, 'OK');
}
throw error;
}
}
error-handler.interceptor.spec.ts
import { Type } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient, HttpErrorResponse } from '@angular/common/http';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
import { NotificationCenterService } from '@app/shared/notification-center.service';
describe('ErrorHandlerInterceptor', () => {
let errorHandlerInterceptor: ErrorHandlerInterceptor;
let http: HttpClient;
let httpMock: HttpTestingController;
let noti: jasmine.SpyObj<NotificationCenterService>;
beforeEach(() => {
const spy = jasmine.createSpyObj('NotificationCenterService', ['open']);
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, RouterTestingModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useFactory: errorHandlerInterceptor,
multi: true
},
{
provide: NotificationCenterService,
useValue: spy
}
]
});
noti = TestBed.get(NotificationCenterService);
http = TestBed.get(HttpClient);
httpMock = TestBed.get(HttpTestingController as Type<HttpTestingController>);
errorHandlerInterceptor = TestBed.get(ErrorHandlerInterceptor);
});
afterEach(() => {
httpMock.verify();
});
it('should redirect to fatal error page upon fatal error', () => {
// Arrange
// Note: here we spy on private method since target is customization here,
// but you should replace it by actual behavior in your app
spyOn(ErrorHandlerInterceptor.prototype as any, 'errorHandler').and.callThrough();
// Act
http.get('/toto').subscribe(
res => fail('should error'),
(error: HttpErrorResponse) => {
// Assert
expect((ErrorHandlerInterceptor.prototype as any).errorHandler).toHaveBeenCalled();
}
);
httpMock.expectOne({}).flush(null, {
status: 404,
statusText: 'Not Found!'
});
});
});
The answer might be too late, but this might help for someone.
Update the test case like this
import { RouterTestingModule } from '@angular/router/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
.............................
.............................
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TestingComponents],
imports : [
............
............
............
............
MatListModule,
HttpClientTestingModule,
RouterTestingModule.withRoutes([]),
],
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With