我正在尝试理解Jest的异步测试。
我的模块有一个函数,它接受一个布尔值并返回一个值的Promise。executer函数调用setTimeout
,在超时回调中,promise根据最初提供的布尔值进行解析或拒绝。代码看起来像这样:
const withPromises = (passes) => new Promise((resolve, reject) => {
const act = () => {
console.log(`in the timout callback, passed ${passes}`)
if(passes) resolve('something')
else reject(new Error('nothing'))
}
console.log('in the promise definition')
setTimeout(act, 50)
})
export default { withPromises }
我想用Jest测试一下。我想我需要使用Jest提供的模拟计时器,所以我的测试脚本看起来有点像这样:
import { withPromises } from './request_something'
jest.useFakeTimers()
describe('using a promise and mock timers', () => {
afterAll(() => {
jest.runAllTimers()
})
test('gets a value, if conditions favor', () => {
expect.assertions(1)
return withPromises(true)
.then(resolved => {
expect(resolved).toBe('something')
})
})
})
无论我是否调用jest.runAllTimers()
,我都会得到以下错误/失败的测试
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
你能解释一下我哪里出错了吗?我可以做些什么来获得一个通过测试,让promise按预期解决?
2条答案
按热度按时间gj3fmq9x1#
对
jest.useFakeTimers()
的调用将每个计时器函数模拟为您必须控制的函数。您可以手动将计时器提前,而不是自动运行计时器。jest.runTimersToTime(msToRun)
函数将其提前msToRun
毫秒。很常见的情况是,您希望快进到每个计时器都已经过去,计算所有计时器完成所需的时间会很麻烦,因此Jest提供了jest.runAllTimers()
,它假装已经过去了足够的时间。测试中的问题是,您从未在测试中调用
jest.runAllTimers()
,而是在afterAll
钩子中调用它,该钩子在测试完成后被调用。在测试过程中,计时器保持为零,因此实际上不会调用回调,Jest会在预定义的时间间隔(默认值:5s),以防止被潜在的无休止的测试卡住。只有在测试超时后,才调用jest.runAllTimers()
,此时它不做任何事情,因为所有测试都已经完成。你需要做的是启动promise,然后提前计时器。
p1iqtdky2#
所以,我遇到了一个类似的问题,我想用
setTimeout()
伪造一个异步函数--它返回一个promise。但是我一直得到一个Exceeded timeout...
错误。我在
async await
语法中修复它时遇到了一些问题。最后,我通过将const x = await ...
分成两行并将jest.runAllTimers()
放在它们之间来解决这个问题。(您也可以在相同的方法中使用jest.advanceTimersByTime()
)。下面是一个完整的测试,我用settime伪造一个promise:
PS.如果你有多个测试,你可能会更好地把
useFakeTimers
和useRealTimers
放进beforeEach
和afterEach
块。