NullInjectorError: StaticInjectorError (DynamicTestModule) [ErrorHandlerInterceptor -> Router]: - PullRequest
0 голосов
/ 28 октября 2019

Я уже добавил RouterTestingModule в свой импорт для моего модульного теста. Но все равно выдает следующую ошибку.

Единственное отличие состоит в том, что моя страница маршрутизации отличается от нормы.

Я приложил свои коды для справки.

Что мне нужно изменить? Или как мне проверить мой перехватчик, используя мой класс маршрутизатора?

Консоль:

 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!'
    });
  });
});
...