Angular 15, want to test switchMap, filter, tap and take.
I'm trying to test my observable:
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null)
private refreshTokenSubject$ = this.refreshTokenSubject.asObservable()
handleRefresh(){
return this.refreshTokenSubject$.pipe(
tap(() => console.log('refresh token')),
filter((token) => token)),
take(1),
switchMap((token) => {
return next.handle(this.addToken(req,token);
})
)
}
I'm doing this:
beforeEach(()=>{
interceptor = TestBed.inject(RefreshTokenInterceptor)
requestMock = new HttpRequest("GET", "/fakeRequest")
})
it("should", () => {
interceptor["addToken"] = jest.fn().mockReturnValue(requestMock)
const next = {
handle: jest.fn().mockImplementation(()=>{
return of()
}
} as HttpHandler
const result = interceptor["refreshTokenSubject$"]
interceptor["handleRefresh"](requestMock, next)
result.subscribe(() => {
expect(next.handle).toBeCalled()
})
})
the test pass, but coverage is saying that the tap, filter, take and switchMap lines are not being tested
Coverage is not necessarily a good metric for test quality (sometimes things can't be covered). That being said, you can still work you way through 100% coverage (as reported by static analysis and coverage reports), and then real 100% coverage (every single possible path is covered).
tap
=> mockconsole.log
and assert on the amount of invocationsfilter
=> test at least once for a truthy token and once for a falsy tokentake
=> mockswitchMap
to assert on the amount of times your callback is invokedswitchMap
=> always the tricky one to test. Add a controlled delay/debounce in your test subject's emissions so that you can emit before it expires and the switchMap is guaranteed to occur. Then assert on the amount of invocations. If you can mock yourhandle
to check that it has been "cancelled"/"switched" correctly and semantically