34

I'm working through the Angular2 testing guide and wish to write a test for the ngOnInit() function. The one from the Routing section of the programming guide has this format:

let org: Org = null;

ngOnInit(): void {
  let that = this;

  this.route.data
    .subscribe((data: { org: Org }) => {
      that.org = data.org;
    });
}

This is fulfilled through a resolver, like:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Org> {
  let id = this.authService.user.orgId;

  return this.orgService
    .getOrg(id)
    .map(
      (org: Org) : Org => {

        if(org) {
          return org;
        } else { 
          // If  the Org isn't available then the edit page isn't appropriate.
          this.router.navigate(['/provider/home']);
          return null;
        }
     })
    .first();
}

The code works OK, but I'm not sure how to write a test for ngOnInit. The examples available to me assume that an embedded OrgService can be replaced by a MockOrgService. However, all I have is a resolver.

I'll eventually figure out how to test the resolver on its own. Are there any useful tests I can do with a resolver-based ngOnInit?

ruffin
  • 16,507
  • 9
  • 88
  • 138
Jerome P Mrozak
  • 1,907
  • 4
  • 21
  • 33
  • I think testing ngOnInit should be the Angular team's responsibility, you should just need to test the methods that you are calling from it – Gerard Simpson Aug 09 '17 at 06:50
  • Hi. How did you unit test the Resolve class on its own? I'm looking to do that, just wondering what your solution was – Drenai Apr 16 '18 at 14:44

2 Answers2

44

What is the behavior or the ngOnInit method? All it does is assign the value of the org when the route data is resolved. So that's all you really need to test.

let routeStub;

beforeEach(() => {
  routeStub = {
    data: null
  }

  TestBed.configureTestingModule({
    providers: [
      { provide: ActivatedRoute, useValue: routeStub }  
    ]
  })
})

it('should assign org when route is resolved', async(() => {
  let org = new Org()
  routeStub.data = Observable.of(org)

  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(component.org).toEqual(org)
  })
}))
River
  • 8,585
  • 14
  • 54
  • 67
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • 6
    Hot stuff! That is the third time you've saved me, because you also answered another Q without knowing it. That is: How do I get rid of the "No provider for Activated Route!" error. Thanks, Jerome. – Jerome P Mrozak Mar 08 '17 at 04:28
  • 1
    async() (2nd parameter of it() ) should be used if the test body makes an XHR call, otherwise use fakeAsync: https://angular.io/guide/testing#async-test-with-async – Snook Mar 15 '19 at 06:36
  • 2
    fixture.whenStable() saved my day! – yww325 Apr 16 '20 at 22:35
  • Would you be able to assist with an issue I'm having with a unit test failing as a result of using route params in ngOnInit(). Here is the stack link: https://stackoverflow.com/questions/64345423/how-would-i-mock-route-queryparams-in-ngoninit-in-a-spec-test – D.Hodges Oct 14 '20 at 02:23
  • @Paul, would you be able to assist with a similar issue I'm having? https://stackoverflow.com/questions/64345423/how-would-i-mock-route-queryparams-in-ngoninit-in-a-spec-test – D.Hodges Oct 15 '20 at 14:44
  • Can you please answer my question also: https://stackoverflow.com/questions/70907350/how-to-write-unit-test-for-ngoninit-with-jasmine-karma/70907621#70907621 – Tanzeel Jan 29 '22 at 17:13
26

I was trying to test ngOnInit() for a component, and unfortunately the accepted answer didn't work for me. However, this did:

describe('your test', () => {
  beforeEach(async() => {
    // set up your component as necessary

    component.ngOnInit();

    await fixture.whenStable();
  });

  it('should verify your test', () => {
    // run your expectation
  });
});
Ian Yoder
  • 307
  • 3
  • 2
  • 1
    generally we do TestBed.createComponent(...) to get the component which I suppose calls ngOnInit. Wouldn't we end up calling ngOnInit twice? – Manu Chadha Feb 20 '19 at 19:34
  • Calling "component.ngOnInit()" is not necessary unless your unit test creates a new object outside of the "beforeEach" function call. – Ken Roy Jan 11 '21 at 13:39
  • @Ken That is not the behavior I am seeing on my project. I can verify this by attaching a spy to ngOnInit and then await a stable fixture. – Kirk Sefchik Aug 31 '21 at 17:48