First off, i'm just new to unit testing or testing in general so i'm still wrapping my head around some concepts. Already got the basic of unit testing and I'm also currently learning about rxjs marble testing, so currently i'm stuck on how to test searching w/c functions the same way with the code in the documentation.
So Let's use the code from the tour of heroes in angular documentation
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),
// ignore new term if same as previous term
distinctUntilChanged(),
// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
Here's my current test looks like
const searchResults$ = (inputs$: Observable<string>) =>
inputs$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((term: string) => fakeHeroService.searchHeroes(term))
);
it('should return the correct results', () => {
scheduler.run(helpers => {
const { cold, hot, expectObservable } = helpers;
// these are the search terms typed by user, observable
// emitted by this.searchTerms
const inputMarbles = '^-a 300ms b-c 300ms';
// each emitted response by each service call
const outputMarbles = '-- 300ms a-- 300ms c';
// verify that service is called N times
// verify that it's passed with certain argument per run
searchServiceSpy = spyOn(heroService, 'searchHeroes').and.returnValue(
cold(outputMarbles)
);
const source$ = hot(inputMarbles);
const output$ = source$.pipe(searchResults$);
expectObservable(output$).toBe(outputMarbles);
/* expect(fakeSearchService.getMatches).toHaveBeenCalledTimes(2); */
});
});
I just can't get it working.
I suggest testing each part of the chain (debounce, disticnt, switchMap) in a separate test.
You can use observer-spy with combination of fakeAsync
for much easier tests.
For example, to test the debounce
you can write something like this (the following code might not be complete, but this is just to illustrate the point) -
import {subscribeAndSpyOn} from '@hirez_io/observer-spy';
it('should debounce by 300 ms', fakeAsync(() => {
// basically with "debounce" you only care if 2 triggers happened and enough time passed,
// the number of results should be 1...
const observerSpy = subscribeAndSpyOn(serviceUnderTest.heroes$);
serviceUnderTest.searchTerms.next();
tick(100);
serviceUnderTest.searchTerms.next();
tick(300);
expect(observerSpy.getValuesLength).toBe(1);
}));
And write similar tests for the others that uses the "just enough principle" to setup the conditions for other operators in the chain.