如何在单元测试中模拟 TS class
How to mock TS class in unit tests
考虑以下代码片段:
import {Calendar} from '@fullcalendar/core';
...
ngAfterViewInit() {
this.calendar = new Calendar(this.element.nativeElement, config);
this.calendar.render();
}
我正在使用 fullcalendar 插件,但它与我原来的问题无关,我想,它可能是任何其他依赖项。所以插件创建了一个日历视图。测试日历行为由 fullcalendar 团队负责,而我负责测试日历集成。所以我需要测试日历是否已使用正确的配置初始化,因此我想省略真正的构造函数并检索参数。而且我也不想创建日历的实例。
如何在我的测试中模拟 Calendar
class?
包装库调用是一种很好的做法。首先,测试它们更容易,如果库界面会发生变化,您只需在一个位置更改代码,并在其余代码中保留您自己的界面。
因此,您的问题的一种解决方案是将日历创建包装在工厂服务中,例如:
@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
是否运行 returns 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))
})
})
考虑以下代码片段:
import {Calendar} from '@fullcalendar/core';
...
ngAfterViewInit() {
this.calendar = new Calendar(this.element.nativeElement, config);
this.calendar.render();
}
我正在使用 fullcalendar 插件,但它与我原来的问题无关,我想,它可能是任何其他依赖项。所以插件创建了一个日历视图。测试日历行为由 fullcalendar 团队负责,而我负责测试日历集成。所以我需要测试日历是否已使用正确的配置初始化,因此我想省略真正的构造函数并检索参数。而且我也不想创建日历的实例。
如何在我的测试中模拟 Calendar
class?
包装库调用是一种很好的做法。首先,测试它们更容易,如果库界面会发生变化,您只需在一个位置更改代码,并在其余代码中保留您自己的界面。
因此,您的问题的一种解决方案是将日历创建包装在工厂服务中,例如:
@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
是否运行 returns 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))
})
})