I am currently trying to test a function which calls a http request service and then does something in the subscribe part (calls a function and sets a variable). My approach so far was to just call the function and I thought the request-service will be called automatically and so the subscribe part will be executed. However, I feel like this is not the way of doing it as it's not working.
The function I want to test:
public trainBot() {
this.isTraining = true;
this.requestsService.trainModel(this.botId, false)
.subscribe(response => {
this.trainingStatus = this.trainingStatusMapping[response['status']];
this.pollTrainingStatus();
});
}
My test so far (which does not work).
it('should poll the training status', () => {
spyOn(component, 'pollTrainingStatus').and.callThrough();
component.trainBot();
fixture.detectChanges();
expect(component.pollTrainingStatus).toHaveBeenCalled();
});
So, can anyone tell me how to test that part inside the .subscribe(... part?
Update:
as someone suggested I added returnValue and async to my test. They are still not working, but looking like that now:
it('should poll the training status', fakeAsync(() => {
component.trainBot();
spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
spyOn(component, 'pollTrainingStatus').and.callThrough();
fixture.detectChanges();
tick(1);
expect(service.trainModel).toHaveBeenCalled();
expect(component.pollTrainingStatus).toHaveBeenCalled();
}));
The Error is the same
Firstly, You need to create your Spies BEFORE you run the method trainBot(). That should fix your tests.
it('should poll the training status', () => {
spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
spyOn(component, 'pollTrainingStatus');
component.trainBot();
expect(service.trainModel).toHaveBeenCalled();
expect(component.pollTrainingStatus).toHaveBeenCalled();
}));
However, let's talk about your testing strategies.
To be honest, you're testing a component, not the service, so you shouldn't be letting the service method call through.
spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
Additionally, a unit test should test the smallest thing possible. You're actually testing the callback here, and the callback should probably be a named method instead of an anonymous arrow function. Then you can test and verify the callback's functionality in other tests.
public trainBot() {
this.isTraining = true;
this.requestsService.trainModel(this.botId, false)
.subscribe(response => this.onTrainbotSuccess(response));
}
public onTrainbotSuccess(response) {
this.trainingStatus = this.trainingStatusMapping[response['status']];
this.pollTrainingStatus();
}
In this test, you can test that the response method is getting called
it('should call service.trainModel', () => {
spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
component.trainBot();
expect(service.trainModel).toHaveBeenCalled();
});
it('should send success responses to onTrainbotSuccess()', () => {
spyOn(component, 'onTrainbotSuccess');
spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
component.trainBot();
expect(component.onTrainbotSuccess).toHaveBeenCalled();
});
Now we can write tests for specifically what the success callback does.
it('should poll the training status', () => {
spyOn(component, 'pollTrainingStatus');
component.onTrainbotSuccess({'status': 'training'});
expect(component.pollTrainingStatus).toHaveBeenCalled();
});
The function passed to subscribe()
is called asynchronously. This means that your assertion is run before this.pollTrainingStatus()
is called. You need to use async()
or fakeAsync()
utility function .
In code can look like this (if using fakeAsync()
):
import { fakeAsync } from '@angular/core/testing';
it('should poll the training status', fakeAsync(() => {
...
expect(component.pollTrainingStatus).toHaveBeenCalled();
}));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.