我对生命周期钩子与Jasmine测试的关系感到困惑。 LifeCycle Angular doc没有提到测试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( );
});
对于舒森来说这是从前一段时间开始的,我已经有一段时间没看过这个了。希望它会有所帮助。注意,我使用的是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( );
});
//
答案 0 :(得分:2)
我经常在必要时直接调用每个规范的生命周期钩子。这很有效。
因为这可以在调用ngAfterViewInit()
或ngOnInit()
之前灵活地处理任何数据。
我也看到过几个角度库测试规范以同样的方式使用它。例如,检查此videogular规范文件。因此手动调用这些方法没有坏处。
此处也复制相同的代码,以避免将来破坏链接。
it('Should hide controls after view init', () => {
spyOn(controls, 'hide').and.callFake(() => {});
controls.vgAutohide = true;
controls.ngAfterViewInit();
expect(controls.hide).toHaveBeenCalled();
});
答案 1 :(得分:0)
我们不能直接从规范中调用生命周期挂钩,但可以调用自定义方法。因为要调用生命周期书,我们需要使用Fixture创建组件的实例。
示例:在我的示例中,我需要将padding-left和right设置为0,因为bootstrap默认情况下会左右填充一些,因此我需要将其删除。
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');
});
});