Search code examples
jasmineangular6angular-test

How to test the code logic of ngOnInit in Jasmine and Angular


My component looks for presence of a parameter in the route in ngOnInit. If the parameter is not present, it shows error. I want to test this logic.

ngOnInit() {
    this.id = this.route.snapshot.paramMap.get("id");
    if(this.id != null) {
...    } else{
      console.log("didn't get id from the route");
      this.showDialog(...);
    }
  }

I wrote the following spec. In the spec, the parameter is not passed in the route

 beforeEach(async() => {

    fixture = TestBed.createComponent(QuestionDetailsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

fit('should show error if question details of a question can\'t be retrieved', () => {
    spyOn(component,'showDialog');
    expect(componetn.showDialog).toHaveBeenCalled();
  });

but my test case fails with reason Expected spy showDialog to have been called.

I suppose the issue is that showDialog gets called when the component gets created before the it is called.

How do I test the logic in ngOnInit? I need the component before I can test it (i.e. call it) and I want to test the logic which gets executed while the component is being created.


Solution

  • To test the ngOnInit method, you just need to call it:

    component.ngOnInit();
    

    And the route value can be spied:

    spyOn(component.route.snapshot.paramMap,"get").and.returnValue("some_id");
    

    Also, you can change the returned value. For example:

    fit("should ...", () => {
      let mock_id = null;
      spyOn(component,"showDialog");
    
      spyOn(component.route.snapshot.paramMap,"get").and.callFake(() => {
          return mock_id;
      });
    
      component.ngOnInit();
      expect(componetn.showDialog).toHaveBeenCalled();
      expect(componetn.showDialog).toHaveBeenCalledTimes(1);
    
      mock_id = "some_value";
      component.ngOnInit();
      expect(...).to..
      ...
      expect(componetn.showDialog).toHaveBeenCalledTimes(1);
    
      mock_id = "another_value";
      component.ngOnInit();
      expect(...).to..
      ...
      expect(componetn.showDialog).toHaveBeenCalledTimes(1);
    });