Angular Unit Test if Component calls Http Service method : Error: <spyOn> : could not find an object to spy upon
Angular Unit Test if Component calls Http Service method : Error: <spyOn> : could not find an object to spy upon
我的目的是测试组件方法是否调用服务方法。服务方法实现是 Post,但是我对 post 机制不感兴趣,因为我打算在服务中测试它,而我只想知道是否调用了正确的服务方法。
我是单元测试的新手,但是错误指示如下使用 spyon要创建服务对象,它需要构造函数中的 HttpClient,我已经尝试了很多解决方案,此时我已经阅读了几个小时,将不胜感激。
最好的,
SC
单元测试
describe('SchedulerComponent', () => {
let component : SchedulerComponent;
let fixture : ComponentFixture<SchedulerComponent>;
let schedulerReportService : SchedulerReportService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SchedulerComponent ],
imports: [BrowserAnimationsModule,
MatSlideToggleModule,
MatRadioModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatNativeDateModule,
MatDatepickerModule,
NativeDateModule,
NgxMaterialTimepickerModule,
ReactiveFormsModule,
FormsModule,
HttpClientTestingModule],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers: [{provide : SchedulerReportService}]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SchedulerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
fit('onSubmit should call scheduleReportService',inject([SchedulerReportService], (service: SchedulerReportService) => {
let scheduleServiceSpy = spyOn(schedulerReportService, 'submitScheduledReport') ;
let submitReportSpy = spyOn(component, 'onSubmit');
submitReportSpy.and.callThrough();
expect(scheduleServiceSpy).toHaveBeenCalled();
}))
对应的服务代码如下
@Injectable({
providedIn: 'root'
})
export class SchedulerReportService {
constructor(private http: HttpClient) { }
submitScheduledReport(servicerequest: ScheduleService) {
console.log(servicerequest)
// const headers = new HttpHeaders({'key':'value'});
// return this.http.post<ScheduleService>(localUrl, servicerequest, {headers : headers} ).pipe(
// retry(1), catchError(this.handleError<ScheduleService>('scheduled report post error')));
}
组件包含触发服务的方法
export class SchedulerComponent implements OnInit {
constructor(private fb: FormBuilder,
private schedulerReportService: SchedulerReportService) {
onSubmit(){
let report = this.schedulerForm.value;
let scheduleServiceModel = new ScheduleService(report)
this.schedulerReportService.submitScheduledReport(scheduleServiceModel);
}
}
要专门解决上面代码中的问题,您需要在调用 spyOn
之前设置服务实例。像这样:
schedulerReportService = fixture.debugElement.injector.get(SchedulerReportService);
...
let scheduleServiceSpy = spyOn(schedulerReportService, submitScheduledReport');
不过,我推荐另一种方法,即使用服务间谍存根。由于您不需要测试您的服务,只需调用一个服务方法,您就不需要注入原始 SchedulerReportService
,而是可以像这样向 Angular 提供服务对象间谍:
describe('SchedulerComponent', () => {
let component : SchedulerComponent;
let fixture : ComponentFixture<SchedulerComponent>;
let schedulerReportService = jasmine.createSpyObj('SchedulerReportService', ['submitScheduledReport']);
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SchedulerComponent ],
imports: [BrowserAnimationsModule,
MatSlideToggleModule,
MatRadioModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatNativeDateModule,
MatDatepickerModule,
NativeDateModule,
NgxMaterialTimepickerModule,
ReactiveFormsModule,
FormsModule,
HttpClientTestingModule],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers: [{provide : SchedulerReportService, useValue: schedulerReportService}]
})
.compileComponents();
fixture = TestBed.createComponent(SchedulerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('onSubmit should call scheduleReportService', () => {
component.onSubmit();
expect(schedulerReportService.submitScheduledReport).toHaveBeenCalled();
}));
通过这种方式,您可以测试 schedulerReportService.submitScheduledReport
的调用没有原始服务 http 调用的开销。
我的目的是测试组件方法是否调用服务方法。服务方法实现是 Post,但是我对 post 机制不感兴趣,因为我打算在服务中测试它,而我只想知道是否调用了正确的服务方法。
我是单元测试的新手,但是错误指示如下使用 spyon要创建服务对象,它需要构造函数中的 HttpClient,我已经尝试了很多解决方案,此时我已经阅读了几个小时,将不胜感激。
最好的, SC
单元测试
describe('SchedulerComponent', () => {
let component : SchedulerComponent;
let fixture : ComponentFixture<SchedulerComponent>;
let schedulerReportService : SchedulerReportService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SchedulerComponent ],
imports: [BrowserAnimationsModule,
MatSlideToggleModule,
MatRadioModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatNativeDateModule,
MatDatepickerModule,
NativeDateModule,
NgxMaterialTimepickerModule,
ReactiveFormsModule,
FormsModule,
HttpClientTestingModule],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers: [{provide : SchedulerReportService}]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SchedulerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
fit('onSubmit should call scheduleReportService',inject([SchedulerReportService], (service: SchedulerReportService) => {
let scheduleServiceSpy = spyOn(schedulerReportService, 'submitScheduledReport') ;
let submitReportSpy = spyOn(component, 'onSubmit');
submitReportSpy.and.callThrough();
expect(scheduleServiceSpy).toHaveBeenCalled();
}))
对应的服务代码如下
@Injectable({
providedIn: 'root'
})
export class SchedulerReportService {
constructor(private http: HttpClient) { }
submitScheduledReport(servicerequest: ScheduleService) {
console.log(servicerequest)
// const headers = new HttpHeaders({'key':'value'});
// return this.http.post<ScheduleService>(localUrl, servicerequest, {headers : headers} ).pipe(
// retry(1), catchError(this.handleError<ScheduleService>('scheduled report post error')));
}
组件包含触发服务的方法
export class SchedulerComponent implements OnInit {
constructor(private fb: FormBuilder,
private schedulerReportService: SchedulerReportService) {
onSubmit(){
let report = this.schedulerForm.value;
let scheduleServiceModel = new ScheduleService(report)
this.schedulerReportService.submitScheduledReport(scheduleServiceModel);
}
}
要专门解决上面代码中的问题,您需要在调用 spyOn
之前设置服务实例。像这样:
schedulerReportService = fixture.debugElement.injector.get(SchedulerReportService);
...
let scheduleServiceSpy = spyOn(schedulerReportService, submitScheduledReport');
不过,我推荐另一种方法,即使用服务间谍存根。由于您不需要测试您的服务,只需调用一个服务方法,您就不需要注入原始 SchedulerReportService
,而是可以像这样向 Angular 提供服务对象间谍:
describe('SchedulerComponent', () => {
let component : SchedulerComponent;
let fixture : ComponentFixture<SchedulerComponent>;
let schedulerReportService = jasmine.createSpyObj('SchedulerReportService', ['submitScheduledReport']);
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SchedulerComponent ],
imports: [BrowserAnimationsModule,
MatSlideToggleModule,
MatRadioModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatNativeDateModule,
MatDatepickerModule,
NativeDateModule,
NgxMaterialTimepickerModule,
ReactiveFormsModule,
FormsModule,
HttpClientTestingModule],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers: [{provide : SchedulerReportService, useValue: schedulerReportService}]
})
.compileComponents();
fixture = TestBed.createComponent(SchedulerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('onSubmit should call scheduleReportService', () => {
component.onSubmit();
expect(schedulerReportService.submitScheduledReport).toHaveBeenCalled();
}));
通过这种方式,您可以测试 schedulerReportService.submitScheduledReport
的调用没有原始服务 http 调用的开销。