How to mock route.snapshot.params?
Asked Answered
P

3

39

In my Angular 4 component I have something like:

constructor(private route: ActivatedRoute) {
}

ngOnInit() {
  this.myId = this.route.snapshot.params['myId'];
}

And I'm trying to create a mock that suppose to look like follows:

class MockActivatedRoute extends ActivatedRoute {
  public params = Observable.of({ myId: 123 });
}    

My test fails with:

TypeError: Cannot read property 'params' of undefined.

How do I suppose to mock it? Have I misunderstood the proper usage of ActivatedRoute and should better use router.subscribe in my component? I saw some complicated examples where people mocked snapshot itself, however for me it looks overcomplicated.


The test itself is quite simple:

describe('ngOnInit', () => {
it('should set up initial state properly',
  () => {
  const component = TestBed.createComponent(MyComponent).componentInstance;
    component.ngOnInit();
    expect(component.myId).toEqual('123');
  });
});

If I simply change a method under the test to something like follows - the test works:

ngOnInit() {
    //this.myId = this.route.snapshot.params['myId'];
    this.route.params.subscribe(params => {
    this.myId = params['myId'];
    });
}

Obviously I need to mock Activated snapshot, but is there a better approach?

Pedal answered 19/10, 2017 at 13:55 Comment(4)
I also tried to do something like const fakeRoutes: Routes = [{path: 'info', data: { catalogId: '123' }, component: StatusComponent},] and then RouterTestingModule.withRoutes(fakeRoutes). Not sure if this syntax is supported trhough.Pedal
Are you trying to use this in unit testing? If so can you post that codeInversely
You are getting params of undefined because your mock is mocking the params observable this.route.params (returns an observable) instead of the snapshot this.route.snapshot.params (returns an object of the params)Inversely
Yeah, thanks. snapshot also uses params, so I thought it should be smart enough to understand that I mocked params. That means if I wanted to mocks both snapshot and params I would need to copy&paste params twice. Anyway, I've managed to resolve it yesterday, thanks for you help.Pedal
P
52

Ok, I've found how to mock ActivatedRoute snapshot in the simple way. Something like this works for me:

providers: [MyComponent, {
  provide: ActivatedRoute,
  useValue: {snapshot: {params: {'myId': '123'}}}
}

Thanks :)

Pedal answered 19/10, 2017 at 15:19 Comment(0)
V
41

If using route.snapshot.paramMap.get( 'uuid' ) instead:

import { ActivatedRoute, convertToParamMap } from '@angular/router';

{
    provide: ActivatedRoute, useValue:
        { snapshot: { paramMap: convertToParamMap( { 'uuid': '99-88-77' } ) } }
}
Vision answered 19/10, 2018 at 15:14 Comment(2)
That's exactly what I needed, thanks! Otherwise there is a this.route.snapshot.paramMap.get is not a function error.Perez
Thanks a lot, your answer save my day.Harty
B
2

Instead of faking it, you can retrieve original route and simply spy on params

   let route: ActivatedRoute;

        beforeEach(() => {
          TestBed.configureTestingModule(...).compileComponents();

          route = TestBed.get(ActivatedRoute);
   })

   it("test",  () => {
      const spyRoute = spyOn(route.snapshot.paramMap, "get")
       spyRoute.and.callFake((paramNameToRead) => {

        switch (paramNameToRead) {
            case "id" : {
                return "value1";
            }
            case "foo" : {
                return null;
            }
            case "bar" : {
                return baz;
            }

        }


    });

}

Begonia answered 2/9, 2022 at 10:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.