This particular setup is quite specific and after scouring the internet, I couldn't find any similar resources. Hence, I decided to post it here in case it proves helpful to someone.
While there are numerous inquiries regarding Jest and the error message Async callback was not invoked
, none seem to address the core issue of utilizing jest.useFakeTimers()
. When employing fake timers, my function should execute instantaneously, yet for some reason Jest seems to be hanging.
I am using Jest version 26 and have manually specified to use modern
timers.
Below is a comprehensive code snippet that showcases the problem:
jest.useFakeTimers('modern')
let setTimeoutSpy = jest.spyOn(global, 'setTimeout')
async function retryThrowable(
fn,
maxRetries = 5,
currentAttempt = 0
) {
try {
return await fn()
} catch (e) {
if (currentAttempt < maxRetries) {
setTimeout(
() => retryThrowable(fn, maxRetries, currentAttempt + 1),
1 * Math.pow(1, currentAttempt)
)
}
throw e
}
}
describe('retryThrowable', () => {
const fnErr = jest.fn(async () => { throw new Error('err') })
it('retries `maxRetries` times if result is Err', async () => {
jest.clearAllMocks()
const maxRetries = 5
await expect(retryThrowable(() => fnErr(), maxRetries)).rejects.toThrow('err')
for (let _ in Array(maxRetries).fill(0)) {
jest.runAllTimers()
await Promise.resolve() // https://stackoverflow.com/a/52196951/3991555
}
expect(setTimeoutSpy).toHaveBeenCalledTimes(maxRetries)
})
})
The complete error message reads as follows:
Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.
at mapper (../../node_modules/jest-jasmine2/build/queueRunner.js:27:45)
Any input or suggestions would be greatly appreciated.
edit 1: I have attempted using --detectOpenHandles
but it did not provide any additional insights.
edit 2: Upon testing the above code snippet in a fresh project, it passed successfully. Therefore, the root cause of the issue must lie elsewhere in my Jest configuration. I will update this post with a solution once I identify the exact source of the problem.