【问题标题】:How to unit test a function which as viewchild如何对作为 viewchild 的函数进行单元测试
【发布时间】:2019-11-27 00:33:04
【问题描述】:

我有一个场景,我需要测试一个作为@Viewchild 引用的函数。

我的组件.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();
            });
        });
    }

所以在我的 Spec 文件中,我做了以下操作

  it('should invoke renderEntityRanges', () => {
    const renderEntityRanges = spyOn(accordionItemComponent, 'renderEntityRanges');
    accordionItemComponent.ngAfterViewInit();
    expect(renderEntityRanges).toHaveBeenCalledWith(ACCORDION_ITEM);
  });

上面的测试用例工作正常。

但我现在确定如何测试此功能renderEntityRanges。

它的剂量是renderEntityRanges,如果type是title,它将检查ACCORDION_ITEM中的类型,然后将服务调用this.renderEngineService.setRootViewContainerRef,输入为this.title。

所以请帮助如何对这个函数进行单元测试。

【问题讨论】:

    标签: angular typescript unit-testing jasmine karma-jasmine


    【解决方案1】:

    为了更正renderEntityRanges,我仅将this.item 删除为item,因为它是作为参数传递的。

        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();
                });
            });
        }
    

    在构造函数中将renderEngineService & changeDetectorRef 设为public 以进行间谍活动:

    public renderEngineService: RenderEngineService,
    public changeDetectorRef: ChangeDetectorRef
    

    你可以尝试如下测试:

    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();
    })
    
    

    并确保ACCORDION_ITEM 的数据同时满足types 和section.rjf = [ some array to iterate over]

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 1970-01-01
      • 2014-02-08
      • 2019-01-02
      • 2019-04-15
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 1970-01-01
      相关资源
      最近更新 更多