Reputation: 19
I have a service class look like this, and trying to add unit test cases which I'm not able figure out, how to test the nested methods with the subscriptions.
TestService {
constructor(@Inject(ENV) private env,
private userService: UserService,
private addressService: AddressService) {}
public getDetails(): void {
this.getUser().subscribe((user) => {
if (user && user !== null) {
this.addressService.getAddress(user).subscribe((address) => {
this.addressService.updateAddress(user).subscribe(() => {
});
});
}
});
}
private getUser(): Observable<string> {
return userService.findUser().pipe(map((response: any) => response.output.user), take(1));
}
}
tried few scenario by spying on the method and returning some mock data but did not work.
here what I tried, and the expectation is if the user is null, I should not have been called getAddress() from addressService, it's giving me error,
it('get user should not call if user is null', async(() => {
service.getDetails();
spyOn(userService, 'getUser').and.returnValue(of('TEST'));
const addressServiceSpy = spyOn(addressService, 'getAddress');
expect(addressServiceSpy).toHaveBeenCalledWith('TEST');
}));
Error:
Expected: 'TEST' Number of calls: 0
Upvotes: 1
Views: 605
Reputation: 15083
I believe you are finding it difficult to test your code because of excessive complexity. It is a good practice NEVER TO NEST SUBSCRIPTIONS
Lets try to break your code into small chunks for easy testing
private getUser(): Observable<string> {
return userService.findUser().pipe(
map(({output}) => output.user),
take(1));
}
public getDetails(): Observable<any> {
return this.getUser().pipe(
mergeMap(user => user ? forkJoin([
this.addressService.getAddress(user),
this.addressService.updateAddress(user)]) : of(null)),
map(([address]) => address)
)
}
Now we can simply subscribe to the observable in the test
it('get user should not call if user is null', async(() => {
spyOn(userService, 'getUser').and.returnValue(of(null));
service.getDetails().subscribe({
next: res => {
expect(res).toBeNull();
}
});
}));
Upvotes: 0