angular - Hur man enhetstestar en funktion som har ViewChild
Jag har ett scenario där jag behöver testa en funktion som har en @Viewchild-referens.
Min component.ts
@ViewChild('accTitle', { read: ViewContainerRef, static: false }) title: ViewContainerRef;
@ViewChild('accText', { read: ViewContainerRef, static: false }) body: ViewContainerRef;
constructor(
private renderEngineService: RenderEngineService,
@Inject(CONTENT_MAPPINGS) private contentMappings: any,
private changeDetectorRef: ChangeDetectorRef
) {}
ngAfterViewInit() {
this.renderEntityRanges(this.item);
}
renderEntityRanges(item: AreasData) {
this.item.sections.forEach(section => {
if (section.type === 'title') {
this.renderEngineService.setRootViewContainerRef(this.title);
} else if (section.type === 'text') {
this.renderEngineService.setRootViewContainerRef(this.body);
}
section.rjf.forEach(rjf => {
const type = this.contentMappings[rjf.type];
this.renderEngineService.createComponent(rjf, type);
this.changeDetectorRef.detectChanges();
});
});
}
Så i min Spec-fil gjorde jag följande
it('should invoke renderEntityRanges', () => {
const renderEntityRanges = spyOn(accordionItemComponent, 'renderEntityRanges');
accordionItemComponent.ngAfterViewInit();
expect(renderEntityRanges).toHaveBeenCalledWith(ACCORDION_ITEM);
});
Ovanstående testfall fungerar bra.
Men jag är nu säker på hur man testar denna funktion renderEntityRanges.
Vad det gör är renderEntityRanges, det kommer att kontrollera typen i ACCORDION_ITEM om type är title, då kommer det att göra ett tjänsteanrop till this.renderEngineService.setRootViewContainerRef med input som this.title.
Så vänligen hjälp hur denna funktion kan enhetstestas.
Svar #1
För att korrigera renderEntityRanges har jag tagit bort this.item till endast item, eftersom det skickas som ett argument.
renderEntityRanges(item: AreasData) {
item.sections.forEach(section => {
if (section.type === 'title') {
this.renderEngineService.setRootViewContainerRef(this.title);
} else if (section.type === 'text') {
this.renderEngineService.setRootViewContainerRef(this.body);
}
section.rjf.forEach(rjf => {
const type = this.contentMappings[rjf.type];
this.renderEngineService.createComponent(rjf, type);
this.changeDetectorRef.detectChanges();
});
});
}
och gör renderEngineService & changeDetectorRef som public i konstruktorn för att spionera:
public renderEngineService: RenderEngineService,
public changeDetectorRef: ChangeDetectorRef
Du kan försöka testa det som:
it('should set Container Ref and create component',()=>{
spyOn(accordionItemComponent.renderEngineService,'setRootViewContainerRef').and.callThrough();
spyOn(accordionItemComponent.renderEngineService,'createComponent').and.callThrough();
spyOn(accordionItemComponent.changeDetectorRef,'detectChanges').and.callThrough();
accordionItemComponent.renderEntityRanges(ACCORDION_ITEM);
expect(accordionItemComponent.renderEngineService.setRootViewContainerRef).toHaveBeenCalled();
expect(accordionItemComponent.renderEngineService.createComponent).toHaveBeenCalled();
expect(accordionItemComponent.changeDetectorRef.detectChanges).toHaveBeenCalled();
})
och se till att ACCORDION_ITEM har data som uppfyller både types och section.rjf=[någon array att iterera över]
