问题
I am trying to test a function that unsubscribes from all subscriptions:
ngOnDestroy() {
this.tryUnsubscribe(this.carsSubscription);
this.tryUnsubscribe(this.partsSubscription);
this.tryUnsubscribe(this.shopsSubscription);
}
This is the test I wrote for the function:
it('should unsubscribe from subscriptions ', () => {
spyOn(component, "tryUnsubscribe");
component.ngOnDestroy();
expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['carsSubscription']);
expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['partsSubscription']);
expect(component.tryUnsubscribe).toHaveBeenCalledWith(component['shopsSubscription']);
});
The problem:
If I comment out a function call, the tests still passes.
ngOnDestroy() {
this.tryUnsubscribe(this.carsSubscription);
//this.tryUnsubscribe(this.partsSubscription);
this.tryUnsubscribe(this.shopsSubscription);
}
Only if I comment out all of these function calls, the test fails:
ngOnDestroy() {
//this.tryUnsubscribe(this.carsSubscription);
//this.tryUnsubscribe(this.partsSubscription);
//this.tryUnsubscribe(this.shopsSubscription);
}
How to properly test this kind of function? What am I doing wrong?
回答1:
I would rewrite your test to the following:
it('should unsubscribe from subscriptions ', () => {
const spy = spyOn(component, 'tryUnsubscribe');
component.ngOnDestroy();
// Check how many times the spy was called
expect(spy).toHaveBeenCalledTimes(3);
});
If you now uncomment one of the tryUnsubscribe
calls, the test should fail as the spy was only called twice.
Another approach would be to mock the subscriptions or just set them to a dummy value to test that inside the ngDestroy
tryUnsubscribe
was called with those 3 component variables:
it('test unsubscribing', () => {
// Mock values
component.carsSubscription = Observable.of(1).subscribe(() => {});
component.partsSubscription = Observable.of(1).subscribe(() => {});
component.shopsSubscription = Observable.of(1).subscribe(() => {});
const spy = spyOn(component, 'tryUnsubscribe').and.callThrough();
component.ngOnDestroy();
// Check how many times the spy was called
expect(spy).toHaveBeenCalledTimes(3);
// Check arguments
expect(spy.calls.all()[0].args[0]).toEqual(component.carsSubscription);
expect(spy.calls.all()[1].args[0]).toEqual(component.partsSubscription);
expect(spy.calls.all()[2].args[0]).toEqual(component.shopsSubscription);
});
Here is a working stackblitz with the test.
回答2:
It is also possible to check all arguments at once using Jasmine calls.allArgs() method:
expect(spy.calls.allArgs()).toEqual([
[component.carsSubscription],
[component.partsSubscription],
[component.shopsSubscription]
]);
Here is modified Fabian Küng's answer in stackblitz.
来源:https://stackoverflow.com/questions/54420277/how-to-test-multiple-sequential-calls-with-jasmine