Jest fake timers with promises

Multi tool use
Multi tool use


Jest fake timers with promises



I'm having a little trouble getting the Jest testing framework (version 23.2.0) to work nicely when using a combination of fake timers and promises. Where am I going wrong?



Let's say I have the following module:


// timing.js

export const timeout = ms =>
new Promise(resolve => {
setTimeout(resolve, ms)
})



And my test file looks like:


// timing.test.js

import { timeout } from './timing'

describe('timeout()', () => {
beforeEach(() => {
jest.useFakeTimers()
})

it('resolves in a given amount of time', () => {
const spy = jest.fn()

timeout(100).then(spy)
expect(spy).not.toHaveBeenCalled()

jest.advanceTimersByTime(100)
expect(spy).toHaveBeenCalled()
})
})



This fails with the following output:


● timeout › resolves in a given amount of time

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called, but it was not called.

15 |
16 | jest.advanceTimersByTime(100)
> 17 | expect(spy).toHaveBeenCalled()
| ^
18 | })
19 | })
20 |

at Object.<anonymous> (src/timing.test.js:17:17)



However, if I remove the promise:


// timing.js
export const timeout = ms => ({
then: resolve => {
setTimeout(resolve, ms)
}
})



... the test will pass


timeout
✓ resolves in a given amount of time (5ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.304s



UPDATE



Although it's not the most elegant solution, I'm currently using the below test instead. It works, but I'm still intrigued why the original one didn't


import { timeout } from './timing'

describe('timeout', () => {
it('resolves in a given amount of time', done => {
setTimeout(() => done(new Error('it didn't resolve or took longer than expected')), 10)
return timeout(9).then(done)
})
})




1 Answer
1



You're not doing anything wrong - it doesn't work at the moment - sorry. The following things have to happen before this will work from our end:


advanceTimeByTime(100)



The problem in a gist is that the .then(spy) only gets called later.


.then(spy)



As we are volunteers - there is no concrete timeline for these things. I hope SimenB does the merge in the coming 2-3 months and I'll follow up with the hook with the V8 team next month.



You can always write an async test:


// note this is an async function now
it('resolves in a given amount of time', async () => {
// this is in a promise.reoslve.then to not 'lock' on the await
Promise.resolve().then(() => jest.advanceTimersByTime(100));
await timeout(100);
});



You can add expectations after the timeout if there is anything else you want to wait for.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

auM,e,TpGeCKQwuHj
NaCK81ZkYRbSDclNv,06 fGQQ2w5q DoPzq3A2NU1fNyYQBmhUHqw Ke y

Popular posts from this blog

Rothschild family

Cinema of Italy