Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Error: No provider for router" while writing Karma-Jasmine unit test cases

People also ask

How can you set up a router for testing Angular?

We can test routing in Angular by using RouterTestingModule instead of RouterModule to provide our routes. This uses a spy implementation of Location which doesn't trigger a request for a new URL but does let us know the target URL which we can use in our test specs.


You need to import RouterTestingModule when setting up the test module.

  /* tslint:disable:no-unused-variable */
  import { async, ComponentFixture, TestBed } from '@angular/core/testing';
  import { By } from '@angular/platform-browser';
  import { DebugElement } from '@angular/core';

  import { RouterTestingModule } from '@angular/router/testing';

  import { MyNewComponentComponent } from './my-new-component.component';

  describe('MyNewComponentComponent', () => {
    let component: MyNewComponentComponent;
    let fixture: ComponentFixture<MyNewComponentComponent>;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [RouterTestingModule],
        declarations: [ MyNewComponentComponent ]
      })
      .compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(MyNewComponentComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });

    it('should create', () => {
      expect(component).toBeTruthy();
    });
  });

Edit: example with mock DummyService

  /* tslint:disable:no-unused-variable */
  import { async, ComponentFixture, TestBed } from '@angular/core/testing';
  import { By } from '@angular/platform-browser';
  import { DebugElement } from '@angular/core';

  import { RouterTestingModule } from '@angular/router/testing';

  import { MyNewComponentComponent } from './my-new-component.component';

  // import the service
  import { DummyService } from '../dummy.service';

  // mock the service
  class MockDummyService extends DummyService {
    // mock everything used by the component
  };

  describe('MyNewComponentComponent', () => {
    let component: MyNewComponentComponent;
    let fixture: ComponentFixture<MyNewComponentComponent>;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [RouterTestingModule],
        declarations: [MyNewComponentComponent],
        providers: [{
          provide: DummyService,
          useClass: MockDummyService
        }]
      })
        .compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(MyNewComponentComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });

    it('should create', () => {
      expect(component).toBeTruthy();
    });
  });

Add RouterTestingModule for configureTestingModule testCase

==> imports: [RouterTestingModule],

import {RouterTestingModule} from '@angular/router/testing';

beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule], // <====
providers: [],
declarations: [],
});
});

I get the same kind of error and I want to share my solution to help others

The Error I get in Karma

error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'RouterModule', 'Router', 'Function', 'Function' ] })
NullInjectorError: R3InjectorError(DynamicTestModule)[RouterModule -> Router -> Function -> Function]: 
  NullInjectorError: No provider for Function!

inventory-view.component.ts

@Component({
  selector: 'app-inventory-view',
  templateUrl: './inventory-view.component.html',
  styleUrls: ['./inventory-view.component.scss'],
  animations: []
})
export class InventoryViewComponent implements OnInit, AfterViewInit, OnDestroy {

  constructor(
    public router: Router, // <--- here was the problem
    public activatedRoute: ActivatedRoute
  ) { }

In my test file

inventory-view.component.spec.ts

import { HttpClientModule } from '@angular/common/http';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ActivatedRoute, convertToParamMap, Router } from '@angular/router';

const ActivatedRouteSpy = {
  snapshot: {
    paramMap: convertToParamMap({
      some: 'some',
      else: 'else',
    })
  },
  queryParamMap: of(
    convertToParamMap({
      some: 'some',
      else: 'else',
    })
  )
};

const RouterSpy = jasmine.createSpyObj(
  'Router',
  ['navigate']
);

describe('InventoryViewComponent', () => {
  let component: InventoryViewComponent;
  let fixture: ComponentFixture<InventoryViewComponent>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule,
        RouterTestingModule,
      ],
      declarations: [ InventoryViewComponent ],
      providers: [
        { provide: ActivatedRoute,   useValue: ActivatedRouteSpy    },
        { provide: Router,           useValue: RouterSpy            }
      ]
    })
    .compileComponents();
  }));

  beforeEach(waitForAsync(() => {
    fixture = TestBed.createComponent(InventoryViewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }));

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});