web-dev-qa-db-ja.com

JasmineテストのAfterViewInitのライフサイクルフック

Jasmineのテストとの関係でライフサイクルフックについて混乱しています。 LifeCycle Angularドキュメントはテストについて言及していません https://angular.io/guide/lifecycle-hooks 。テストドキュメントはOnChangeについてのみ言及しています https: //angular.io/guide/testing 。次のようなサンプルコンポーネントがあります。

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');
    }
    ...
}

注意として、これはAngular最新ダウンロードのCLIアプリです。Karmaではコンソールログが表示されないため、navは設定されていません。現在、スペックで次のように呼び出しています。

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

これを処理するこの適切な方法はありますか?

Shussonの場合、これはしばらく前からのものであり、私はこれをしばらく見ていません。お役に立てば幸いです。注意:私はPrimeface Primengライブラリを使用しています:

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( );
  });
  //
12
P. Huhn

必要に応じて、各仕様からライフサイクルフックを直接呼び出すことがよくあります。そして、これはうまくいきます。これは、ngAfterViewInit()またはngOnInit()を呼び出す前にデータを操作する柔軟性を提供するためです。

私もいくつかのangularライブラリが同じ方法でそれを使用してスペックをテストしています。たとえば、これを確認してください videogular スペックファイル。これらのメソッドを呼び出しても害はありません。手動で。

また、同じコードをここにコピーします。これは、リンクが将来壊れないようにするためです。

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

        controls.vgAutohide = true;

        controls.ngAfterViewInit();

        expect(controls.hide).toHaveBeenCalled();
});
2
Amit Chigadani

スペックからライフサイクルフックを直接呼び出すことはできませんが、カスタムメソッドを呼び出すことはできます。ライフサイクルブックを呼び出すには、フィクスチャを使用してコンポーネントのインスタンスを作成する必要があるためです。

例:私の例では、bootstrapはデフォルトで左右にパディングを与えるため、削除する必要があります。のようにpadding-leftとrightを0に設定する必要があります。 =

HTMLファイル-app.component.ts

import { Component, ViewChild, ElementRef, Renderer2 } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('navCol', { static: true }) navCol: ElementRef;

  constructor(private renderer: Renderer2) {  }

  ngAfterViewInit() {
    this.renderer.setStyle(this.navCol.nativeElement, 'padding-left', '0px');
    this.renderer.setStyle(this.navCol.nativeElement, 'padding-right', '0px');
  }
}

app.component.spec.ts

import { TestBed, async } from '@angular/core/testing';

describe('AppComponent', () => {
  it('should load page and remove padding', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.componentInstance.ngAfterViewInit();
    const styles = window.getComputedStyle(fixture.nativeElement);

    expect(styles.paddingLeft).toBe('0px');
    expect(styles.paddingRight).toBe('0px');
  });
});
0
Sahil Shikalgar