'How to use Jest useFakeTimers with RXJS?

My application is primarily using React Redux. We have a few places that use RXJS to simplify things. I just started using jest.useFakeTimers.

I realized that given code like this from(anAsyncMethod).pipe(timeout(FETCH_TOKEN_TIMEOUT)) will trigger a timeout error the second jest.runAllTimers(); fires in my afterEach.

The relevant stack is here:

          stack: 'Error: \n' +
            '    at _super (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js:6:26)\n' +
            '    at new TimeoutErrorImpl (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/operators/timeout.js:21:9)\n' +
            '    at timeoutErrorFactory (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/operators/timeout.js:66:11)\n' +
            '    at AsyncAction.eval (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/operators/timeout.js:44:84)\n' +
            '    at AsyncAction.eval (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/util/caughtSchedule.js:7:21)\n' +
            '    at AsyncAction._execute (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncAction.js:65:18)\n' +
            '    at AsyncAction.execute (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncAction.js:53:26)\n' +
            '    at AsyncScheduler.flush (webpack-internal:///../../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncScheduler.js:26:33)\n' +
            '    at callTimer (/Users/dstein/Repositories/uxp-plugin/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:729:24)\n' +
            '    at Object.next (/Users/dstein/Repositories/uxp-plugin/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:1409:17)\n' +
            '    at Object.runAll (/Users/dstein/Repositories/uxp-plugin/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js:1468:23)\n' +
            '    at FakeTimers.runAllTimers (/Users/dstein/Repositories/uxp-plugin/node_modules/@jest/fake-timers/build/modernFakeTimers.js:75:19)\

Is there any way to work around this issue?



Solution 1:[1]

well looks like anAsyncMethod takes longer than FETCH_TOKEN_TIMEOUT therefore the error is thrown, this is expected.

when you subscribe to your observable you should check for errors:

from(anAsyncMethod).pipe(timeout(FETCH_TOKEN_TIMEOUT)).subscribe(
  res => console.log('ok'),
  err => console.error('timeout')
);

or you can catch the error

from(anAsyncMethod).pipe(
  timeout(FETCH_TOKEN_TIMEOUT),
  catchError(error => of(`Request timed out after: ${FETCH_TOKEN_TIMEOUT}`))
);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Zerotwelve