Reputation: 93
My intention is to test if a Component Method calls a Service Method. The service method implementation is a Post, however I am not interested in the post mechanisms as I plan to test this in the service, rather I just want to know if the proper service method was called.
I am new to Unit testing however the error indicates the usage of spyon as follows Usage spyOn('object, methodName'), indicating that I am not properly creating an instance of the service object to test, however in order to create the service object it requires the HttpClient in the constructor, I have tried so many solutions and I have been reading for hours at this point, help would be greatly appreciate.
Best, SC
The Unit Test
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();
}))
The corresponding service code is as follows
@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')));
}
The component contained a method to trigger the service
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);
}
}
Upvotes: 1
Views: 1367
Reputation: 2690
To specifically address the problem in your code above you need to set the service instance before calling spyOn
. Something like this:
schedulerReportService = fixture.debugElement.injector.get(SchedulerReportService);
...
let scheduleServiceSpy = spyOn(schedulerReportService, submitScheduledReport');
However I recommend another way of doing this which is using a service spy stub. Since you don't need to test your service, only that a service method is called you don't need to inject the original SchedulerReportService
instead you could provide a service object spy to Angular like this:
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();
}));
This way you can test that schedulerReportService.submitScheduledReport
was called without the overhead of the original service http calls.
Upvotes: 2