Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NullInjectorError: StaticInjectorError(DynamicTestModule)[ErrorHandlerInterceptor -> Router]:

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!'
    });
  });
});
like image 984
shadow Avatar asked Nov 06 '22 12:11

shadow


1 Answers

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([]),
      ],
like image 156
rams Avatar answered Nov 15 '22 07:11

rams