【问题标题】:angular jasmine test abstract class with other abstract class角茉莉花测试抽象类与其他抽象类
【发布时间】:2021-10-15 00:16:44
【问题描述】:

我有这个场景问题:

在 Ionic/Angular 项目(ionic v3/Angular v5)中,我有组件 SuppliedVanContainerComponent,它扩展了抽象类 AbstractLoadingClass,而这个类扩展了另一个抽象类 AbstractSubscriberClass.

AbstractLoadingClass 使用LoadingController 一个离子角度服务来显示微调器,并在调用 showLoading 方法时由 SuppliedVanContainerComponent 使用。

问题:当我可以对 jasmine 使用单元测试时,它会显示这些错误:

TypeError: Cannot read properties of undefined (reading '_getPortal')

当我用 jasmine.createSpyObj 模拟 LoadingController 时,它显示了另一个错误并且是:

TypeError: this.loading.present 不是函数

我该如何修复它或者我可以使用抽象类进行测试?

SuppliedVanContainerComponent

    export class SuppliedVanContainerComponent extends AbstractLoadingClass
      constructor(loadingCtrl: LoadingController) {
            super(loadingCtrl);
        }

      ngOnInit(){
        this.showLoading();
      }

AbstractLoadingClass

import {Loading, LoadingController} from 'ionic-angular';
import {LoadingOptions} from 'ionic-angular/umd/components/loading/loading-options';

import {AbstractSubscriberClass} from './abstract-subscriber.class';

export abstract class AbstractLoadingClass extends AbstractSubscriberClass {
  private loading: Loading;
  
  protected constructor(public loadingCtrl: LoadingController) {
    super();
  }
  
  private getCreateLoading(opts?: LoadingOptions) {
    return this.loadingCtrl.create(opts);
  }
  
  showLoading() {
    this.loading = this.getCreateLoading({content: ''});
    this.loading.present();
    this.loading.setContent('');
  }

  hideLoading() {
    this.loading.dismiss();
  }
}

茉莉花测试出错

...
  let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', {
    create: {content: ''},
  })
...
{provide: LoadingController, useValue: fakeLoadingController},

错误:

【问题讨论】:

    标签: angular unit-testing jasmine ionic3 abstract-class


    【解决方案1】:

    感谢@AliF50,我有两个解决方案,我发布了, 第一个解决方案:

    ....
    let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create'])
    ......
    providers: [
    ....
       {provide: LoadingController, useValue: fakeLoadingController},
    ]
    ....
    beforeEach(() => {
        fixture = TestBed.createComponent(SuppliedVanContainerComponent);
        fakeLoadingController.create.and.returnValue({present: () => null, setContent: () => null, dismiss: () => null});
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    

    而且它的工作方式非常简单,无需使用 LoaderController 进行间谍或测试(只是模拟)。

    如果您要使用 Loading 和 spy ,请在此模式下设置:

    .....
      let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create'])
      let fakeLoadingObject = jasmine.createSpyObj<Loading>('Loading', ['present', 'setContent', 'dismiss']);
    .....
    providers: [
    ...
            {provide: LoadingController, useValue: fakeLoadingController},
            {provide: Loading, useValue: fakeLoadingObject},
    ]
    ....
      beforeEach(() => {
        fixture = TestBed.createComponent(SuppliedVanContainerComponent);
        dailyReportsModel = TestBed.get(DailyReportsModel);
        fakeLoadingController.create.and.returnValue(fakeLoadingObject);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
      ....
      it('test fakeLoadingObject', () => {
        expect(fakeLoadingObject.present).toHaveBeenCalled();
      })
    

    感谢@AliF50

    【讨论】:

      【解决方案2】:

      我认为你在嘲笑它不正确,试试这个:

      let fakeLoadingController = jasmine.createSpyObj<LoadingController>('LoadingController', ['create']);
      ...
      {provide: LoadingController, useValue: fakeLoadingController},
      ...
      // before fixture = ..., add this line
      fakeLoadingController.create.and.returnValue({ present: () => null, setContent: () => null, dismiss: () => null });
      // Or if you want spies on present, setContent, dismiss, you could do
      let fakeLoadingObject = jasmine.createSpyObj<any>('FakeLoadingObject', ['present', 'setContent', 'dismiss']);
      // then the line above becomes
      fakeLoadingController.create.and.returnValue(fakeLoadingObject);
      // And then you should have a handle of something like this:
      expect(fakeLoadingObject.present).toHaveBeenCalled();
      

      【讨论】:

      • 谢谢,一切正常!!在两种解决方案中都有效!我不能赞成你的评论:(
      • 没关系,没问题。我很乐意提供帮助。
      猜你喜欢
      • 2020-07-22
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-07-22
      • 1970-01-01
      相关资源
      最近更新 更多