Lifecycle hook of AfterViewInit in Jasmine test

19,834

I often directly call the life cycle hooks from each spec whenever necessary. And this works. Because this gives the flexibility to manipulate any data before calling ngAfterViewInit() or ngOnInit().

I have also seen few angular libraries test spec using it in the same way. For eg, check this videogular spec file. So there is no harm in calling those methods manually.

Also copying the same code here, just to avoid the link to be broken in future.

it('Should hide controls after view init', () => {
        spyOn(controls, 'hide').and.callFake(() => {});

        controls.vgAutohide = true;

        controls.ngAfterViewInit();

        expect(controls.hide).toHaveBeenCalled();
});
Share:
19,834

Related videos on Youtube

Phil Huhn
Author by

Phil Huhn

I am the long standing treasurer of Ann Arbor Computer Society. Given over 33 full length talks at AACS.

Updated on June 06, 2022

Comments

  • Phil Huhn
    Phil Huhn almost 2 years

    I am confused on lifecycle hooks in relationship with Jasmine testing. The LifeCycle Angular doc does not mention testing https://angular.io/guide/lifecycle-hooks. The testing doc only mentions OnChange https://angular.io/guide/testing. I have a sample component as follows:

    import { Component, OnInit, AfterViewInit, OnDestroy, ElementRef } from '@angular/core';
    ...
    @Component({
      selector: 'app-prod-category-detail',
      templateUrl: './prod-category-detail.component.html',
      styleUrls: ['./prod-category-detail.component.css']
    })
    //
    export class ProdCategoryDetailComponent implements OnInit, AfterViewInit, OnDestroy {
        ...
        nav: HTMLSelectElement;
        //
        constructor(
            ...
            private _elementRef: ElementRef ) { }
        ...
        ngAfterViewInit() {
            console.log( 'ProdCategoryDetailComponent: ngAfterViewInit' );
            this.nav = this._elementRef.nativeElement.querySelector('#nav');
        }
        ...
    }
    

    As a note, this is an Angular CLI app with the latest downloads. In Karma, I do not see the console log, therefore nav is never set. I am currently invoking it in my spec as follows:

    beforeEach(() => {
      fixture = TestBed.createComponent(ProdCategoryDetailComponent);
      sut = fixture.componentInstance;
      sut.ngAfterViewInit( );
      fixture.detectChanges( );
    });
    

    Is this proper way of handling this?

    For shusson this is from some time ago and I have not looked at this for some time. Hope it will help. Note, I am using Primeface primeng library:

    describe('ProdCategoryDetailComponent', () => {
      let sut: ProdCategoryDetailComponent;
      let fixture: ComponentFixture< ProdCategoryDetailComponent >;
      let alertService: AlertsService;
      let prodCatService: ProdCategoryServiceMock;
      let confirmService: ConfirmationServiceMock;
      let elementRef: MockElementRef;
      //
      beforeEach(async(() => {
        TestBed.configureTestingModule({
          imports: [
            FormsModule,
            ButtonModule,
            BrowserAnimationsModule
          ],
          declarations: [
            ProdCategoryDetailComponent,
            AlertsComponent,
            ConfirmDialog
          ],
          providers: [
            AlertsService,
            { provide: ProdCategoryService, useClass: ProdCategoryServiceMock },
            { provide: MockBackend, useClass: MockBackend },
            { provide: BaseRequestOptions, useClass: BaseRequestOptions },
            { provide: ConfirmationService, useClass: ConfirmationServiceMock },
            { provide: ElementRef, useClass: MockElementRef }
          ]
        })
        .compileComponents();
      }));
      //
      beforeEach(inject([AlertsService, ProdCategoryService,
          ConfirmationService, ElementRef],
            (srvc: AlertsService, pcsm: ProdCategoryServiceMock,
            cs: ConfirmationServiceMock, er: MockElementRef) => {
        alertService = srvc;
        prodCatService = pcsm;
        confirmService = cs;
        elementRef = er;
      }));
      //
      beforeEach(() => {
        fixture = TestBed.createComponent(ProdCategoryDetailComponent);
        sut = fixture.componentInstance;
        sut.ngAfterViewInit( );
        fixture.detectChanges( );
      });
      //
    
    • Julia Passynkova
      Julia Passynkova almost 7 years
      ngAfterViewInit should be called once with the first fixture.detectChanges( );
    • shusson
      shusson about 6 years
      Can you show us how you configure the TestBed? e.g TestBed.configureTestingModule(...). Also do you actually have any tests? Without an it test, beforeEach will not be called.
  • Girum
    Girum over 4 years
    Hi Sahil Shikalgar, how is the view child not giving you a problem in this situation, and you are saying you don't have to call fixture.ngAfterViewInit();
  • Girum
    Girum over 4 years
    Thanks, @Sahil Shikalgar, I think I was using fixture.detectChanges(), even though my test was not asserting the HTML. I think perhaps most people use fixture.detectChanges() more often than they have to.
  • Sahil Shikalgar
    Sahil Shikalgar over 4 years
    Thanks Girum, I will also check with fixture.detectChanges() instead of doing manual call.