J'ai un peu de mal à faire fonctionner correctement le framework de test Jest (version 23.2.0) lorsque j'utilise une combinaison de faux timers et de promesses. Où vais-je mal?
Disons que j'ai le module suivant:
// timing.js
export const timeout = ms =>
new Promise(resolve => {
setTimeout(resolve, ms)
})
Et mon fichier de test ressemble à:
// 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()
})
})
Cela échoue avec la sortie suivante:
● 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)
Cependant, si je retire la promesse:
// timing.js
export const timeout = ms => ({
then: resolve => {
setTimeout(resolve, ms)
}
})
... le test passera
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
MISE À JOUR
Bien que ce ne soit pas la solution la plus élégante, j'utilise actuellement le test ci-dessous. Cela fonctionne, mais je suis toujours intrigué pourquoi l'original n'a pas
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)
})
})
Vous ne faites rien de mal - cela ne fonctionne pas pour le moment - désolé. Les choses suivantes doivent se produire avant que cela fonctionne de notre côté:
advanceTimeByTime(100)
et que cela fonctionnerait avec des promesses.Le problème dans un Gist est que la .then(spy)
n'est appelée que plus tard .
Comme nous sommes bénévoles - il n'y a pas de calendrier concret pour ces choses. J'espère que SimenB fera la fusion dans les 2-3 prochains mois et je poursuivrai avec le crochet avec l'équipe V8 le mois prochain.
Vous pouvez toujours écrire un test asynchrone:
// 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);
});
Vous pouvez ajouter des attentes après le délai d'attente si vous souhaitez attendre autre chose.