How to unit test a component that depends on parameters from ActivatedRoute?

In angular 8+ there is the RouterTestingModule, which you can use in order to have access to the ActivatedRoute or Router of the component. Also you can pass routes to the RouterTestingModule and create spies for the requested methods of route.

For example in my component I have:

ngOnInit() {
    if (this.route.snapshot.paramMap.get('id')) this.editMode()
    this.titleService.setTitle(`${this.pageTitle} | ${TAB_SUFFIX}`)
}

And in my test I have:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ProductLinePageComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [
        RouterTestingModule.withRoutes([])
      ],
    })
    .compileComponents()
  }))

  beforeEach(() => {
    router = TestBed.get(Router)
    route = TestBed.get(ActivatedRoute)
  })

and later in the 'it' section:

  it('should update', () => {
    const spyRoute = spyOn(route.snapshot.paramMap, 'get')
    spyRoute.and.returnValue('21')
    fixture = TestBed.createComponent(ProductLinePageComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
    expect(component).toBeTruthy()
    expect(component.pageTitle).toBe('Edit Product Line')
    expect(component.formTitle).toBe('Edit Product Line')
    // here you can test the functionality which is triggered by the snapshot
  })

In a similar way, I think you can test directly the paramMap via the spyOnProperty method of jasmine, by returning an observable or using rxjs marbles. It might save some time & also it does not require to maintain an extra mock class. Hope that it is useful and it makes sense.


The simplest way to do this is to just use the useValue attribute and provide an Observable of the value you want to mock.

RxJS < 6

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: Observable.of({id: 123})
  }
}

RxJS >= 6

import { of } from 'rxjs';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: of({id: 123})
  }
}