'Karma tests: Cancelling of Subscription in finalize does not work
I have this scenario: there is a service taking data from BE. Every call of this service (its method) is subscribed and this subscription is saved to Subscription object, so it can be unsubscribed at any time.
There is also a finalize
operator to cancel the subscription when the service call and all its subsequences are done.
In 'real world' everything works fine - finalize
works as expected - cancel subscription after everything is done, problem is testing part. If I expect
the subscription to be null, the test fails, because the subscription is not cancelled, even if finalize
was called (proved by debugging). And what is even more unclear to me, there is a flag isLoading
, which is set before getting data and reset in finalize
and this is reset both in real world and in tests.
// test.component.ts
currentRequestSubscription: Subscription;
isLoading: bool;
setData(): void {
this.isLoading = true;
this.currentRequestSubscription = this.dataService.getData().pipe(
finalize(() => {
this.currentRequestSubscription.unsubscribe();
this.currentRequestSubscription = null;
this.isLoading = false;
}
).subscribe((value) => {
// process value
});
}
// test.component.spec.ts
spyOn(dataService, 'getData').and.returnValue(of(new Data));
component.setData();
expect(component.currentRequestSubscription).toBe(null); // this fails
expect(component.isLoading).toBe(false); // this succeeds
So, what is behind this? Why is one variable reset in finalize
truly reset and the other is not? Is there any way how to handle this correctly?
Solution 1:[1]
The setData
is asynchronous
method, and in your test case you invoke method and then immediately checking for the specific condition as of it is synchronous
method.
use component.setData(false);
with await
await component.setData(false);
expect(eleComponent.currentRequestSubscription).toBe(null); // this fails
expect(eleComponent.isLoading).toBeFalsy; // this succeeds
Note - If the above solution doesn't work, you place your expect
within the setTimeOut
or you can use timer for passage of time.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | random |