【问题标题】:How to mock TS class in unit tests如何在单元测试中模拟 TS 类
【发布时间】:2020-02-24 09:21:38
【问题描述】:

考虑以下代码sn-p:

import {Calendar} from '@fullcalendar/core';

...

ngAfterViewInit() {
  this.calendar = new Calendar(this.element.nativeElement, config);
  this.calendar.render();
}

我正在使用 fullcalendar 插件,但它与我最初的问题无关,我认为它可能是任何其他依赖项。所以插件创建了一个日历视图。测试日历行为由 fullcalendar 团队负责,而我负责测试日历集成。所以我需要测试日历是否已经用正确的配置初始化,因此我想省略真正的构造函数并检索参数。而且我不想创建日历的实例。

如何在我的测试中模拟 Calendar 类?

【问题讨论】:

    标签: typescript unit-testing jasmine


    【解决方案1】:

    包装您的库调用是一种很好的做法。首先,测试它们更容易,如果库接口会改变,您只需在一个位置更改您的代码,并在其余代码中保留您自己的接口。

    因此,您的问题的一种解决方案是将日历创建包装在工厂服务中,例如:

    @Injectable({providedIn:'root'})
    export class FullcalendarFactoryService{
    
      public buildCalendar(element:HTMLElement,config:any){
        return new Calendar(element,config);
      }
    }
    

    在您的组件中,您必须注入您的工厂服务并像这样使用它:

    constructor(public calenderFactory:FullcalendarFactoryService) {
    }
    
    ngAfterViewInit(): void {
        this.calendar = this.calenderFactory.buildCalendar(this.element.nativeElement,this.config);
        this.calendar.render();
    }
    

    为了测试,你可以简单地模拟你的工厂函数,如下所示:

    beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [
            YourComponent
          ],
          providers: [{
            provide: FullcalendarFactoryService,
            useClass: class {
              buildCalendar = jasmine.createSpy('buildCalendar').and.returnValue({
                render: () => true
              });
            }
          }
          ]
        }).compileComponents();
    
        calendarFactory = TestBed.get(FullcalendarFactoryService);
    
    }));
    
    it('should call factory method with element and config', () => {
        const fixture = TestBed.createComponent(AppComponent);
        fixture.detectChanges();
    
        expect(calendarFactory.buildCalendar).toHaveBeenCalledWith(fixture.componentInstance.element.nativeElement, fixture.componentInstance.config);
      });
    
    

    更新:

    要测试服务buildCalendar 函数是否返回Calendar 的实例,您将测试您的服务,如下所示:

    import {FullcalendarFactoryService} from './fullcalendar-factory.service';
    import {Calendar} from '@fullcalendar/core';
    import dayGridPlugin from '@fullcalendar/daygrid'
    
    describe('calendar factory service', () => {
      let factory:FullcalendarFactoryService;
    
      beforeEach(() => {
        factory = new FullcalendarFactoryService();
      })
    
      it('should return calender instance',() => {
        expect(factory.buildCalendar(document.createElement('test'),{plugins:[dayGridPlugin]})).toEqual(jasmine.any(Calendar))
      })
    })
    

    【讨论】:

    • 好点,但你如何测试FullcalendarFactoryServicebuildCalendar 方法返回日历对象?这部分仍然没有被发现。现在我可以测试参数,但它不会测试 buildCalendar 返回 Calendar 实例而不是 undefined。
    • 我用一个如何做到这一点的例子更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-11
    相关资源
    最近更新 更多