The given class has a method which returns a cached stream but that stream can be triggered by another private hot stream which makes the cached stream emits a new value.
The class
export class SomeClass {
private cache: Observable<number>;
private trigger$ = new Subject();
private multiply = 1;
constructor(private num: number) {}
getNumber(): Observable<number> {
return (
this.cache ||
(this.cache = concat(of(void 0), this.trigger$).pipe(
switchMap(() => of(this.num * this.multiply++)),
shareReplay(1)
))
);
}
trigger(): void {
this.trigger$.next();
}
}
Example: https://stackblitz.com/edit/rxjs-gpyc46?file=index.ts
What is the way to test it? This try is failed
it("trigger updates", () => {
testScheduler.run(({ expectObservable }) => {
const num$ = someClass.getNumber();
expectObservable(num$).toBe("a", { a: 3 });
someClass.trigger();
expectObservable(num$).toBe("a", { a: 6 });
someClass.trigger();
expectObservable(num$).toBe("a", { a: 9 });
});
});
Example: https://stackblitz.com/edit/rxjs-test-tricky-flow?file=src%2Fsome-class.spec.ts
UPD: so the problem here that seems it is not possible to mock the trigger$
property.
It would look like this
it("trigger updates", () => {
testScheduler.run(({ hot, expectObservable }) => {
spyOnProperty(someClass, 'trigger$', 'get').and.returnValue(hot('^--b--c'));
const num$ = someClass.getNumber();
expectObservable(num$).toBe("a--b--c", { a: 3, b: 6, c: 9 });
});
});
But the trigger$
property must be changed this way
get trigger$() {
return new Subject();
}
Example: https://stackblitz.com/edit/rxjs-test-tricky-flow-x2arxf?file=src%2Fsome-class.ts