Search code examples
angulartypescriptunit-testingjestjsurl-parameters

Unit testing Angular Router queryParamMap


I am looking to utilize Angular queryParamMap in ngOnInit lifecycle. The goal is to pass queryparam from this component as state to another. Although functionality works like charm, I am unable to unit test the code functionality.

export class AppComponent implements OnInit {

  constructor(private readonly route: Router, private router: ActivatedRoute) {}

  ngOnInit() {
    this.router.queryParamMap.subscribe((resp) => {
      
    const state ={} as any;
    state.token = resp.get('token')
    state.clientID = resp.get('id')
    state.timestamp = resp.get('timeStamp')
      
      this.route.navigate(['/dashboard'],{state})
    });
  }}

And this is my unit test approach with jest

const activatedRouteMock = {
    queryParamMap: of(routes:{token:1,id:2},
    test(key){
return this.routes.key
})
  };



const mockRoute = mock<Router>();

when I do

it('should be defined', () => {
    component.ngOnInit()
expect(mockRoute.navigate).toBeCalledTimes(1)
expect(mockRoute.navigate).toBeCalledWith(['dashboard'], {state:{token:1,id:2}})
});

But I get error as

Expected call 1 Received call 0

I am not sure on how do I unit test this functionality with QueryParamMap as the properties could be null.


Solution

  • In my case I'm using Jest to implement my tests.

    My component constructor and ngOnInit methods look like this:

    constructor(private route: ActivatedRoute){}
    
    ngOnInit(): void {
        this.route.queryParamMap.subscribe((params) => {
            this.partner = params.get('partner')
        }
    }
    

    Then on the test file I create a params object with a mock get function and apply this setup on beforeEach methods:

    const params = {
        get: jest.fn()
    }
    
    describe('MyComponent', () => {
        beforeEach(async () => {
            await TestBed.configureTestingModule({
                imports: [RouterTestingModule],
                declarations: [MyComponent],
                providers: [{
                    provide: ActivatedRoute,
                    useValue: {
                        queryParamMap: of(params)
                    }
                }]
            })
        )
    
        beforeEach(() => {
            fixture = TestBed.createComponent(MyComponent)
            component = fixture.componentInstance
            fixture.detectChanges()
            TestBed.inject(ActivatedRoute)
        )
    }
    

    And in my test case I spy on the get function of my params mocked object, because I set in the provider to return this object inside an observable for the ActivatedRoute.queryParamMap:

    it('should set the partner property to PARTNER_X as in the GET parameter', () => {
          const getParamSpy = jest.spyOn(params, 'get').mockReturnValueOnce('PARTNER_X')
      
          component.ngOnInit()
    
          expect(component.partner).toBe('PARTNER_X')
          expect(getParamSpy).toBeCalledWith('partner')
    })
    

    To get more specific answers it's better to provide more details about your setup, otherwise it's hard to identify what is the problem you may be facing.

    I hope this could be useful.