Reputation: 1919
Consider the following service example
export class AuthService {
private observableCache: { [key: string]: Observable<boolean> } = {};
private resourceCache: { [key: string]: boolean } = {};
constructor(private userService: UserService) { }
isGranted(resource): Observable<boolean> {
if (this.resourceCache[resource]) {
return of(this.resourceCache[resource]);
}
if (this.observableCache[role]) {
return this.observableCache[role];
}
this.observableCache[resource] = this.userService
.getCurrentUser()
.pipe(map((user: User) => user.canAccess(resource)))
.pipe(share());
return this.observableCache[resource];
}
}
In this service I'm checking if user is allowed to review specific resource.
And here is how I'm trying to test it
describe('AuthService', () => {
let service: AuthService;
let userService: any;
beforeEach(() => {
userService = jasmine.createSpyObj('UserService', ['getCurrentUser']);
service = new AuthGuardService(userService);
});
describe('isGranted', () => {
const user: User = {id: 123};
beforeEach(() => {
userService.getCurrentUser.and.returnValue(
hot('-^u', { u: user })
);
});
it('should prove response being cached', () => {
service.isGranted('dashboard').subscribe();
service.isGranted('dashboard').subscribe();
expect(userService.getCurrentUser).toHaveBeenCalledTimes(1);
});
});
});
The aim of the test is to check that resource cache works. But what I notice, is that if I replace the following snippet
service.isGranted('dashboard').subscribe();
service.isGranted('dashboard').subscribe();
With simple
service.isGranted('dashboard');
service.isGranted('dashboard');
The test still works, I'm new to RxJS and marble testing, but as far as I know, Observable should not work until subscribed.
The question - why does it works both ways?
Upvotes: 0
Views: 166
Reputation: 1316
The code the test is working with is asynchronous, try running it using fakeAsync
and tick
it('should prove response being cached', fakeAsync(() => {
service.isGranted('dashboard').subscribe();
service.isGranted('dashboard').subscribe();
tick();
expect(userService.getCurrentUser).toHaveBeenCalledTimes(1);
}));
Look at https://angular.io/guide/testing#component-with-async-service for more information.
Upvotes: 1