【问题标题】:Testing a Promise using setTimeout with Jest使用 setTimeout 和 Jest 测试 Promise
【发布时间】:2018-03-24 10:44:44
【问题描述】:

我正在尝试理解 Jest 的异步测试。

我的模块有一个函数,它接受一个布尔值并返回一个值的 Promise。执行器函数调用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.

你能解释一下我哪里出错了,我可以做些什么来获得一个通过测试,保证按预期解决?

【问题讨论】:

    标签: javascript testing asynchronous jestjs


    【解决方案1】:

    jest.useFakeTimers() 的调用使用您必须控制的一个来模拟每个计时器功能。您可以手动推进计时器,而不是自动运行计时器。 jest.runTimersToTime(msToRun) 函数会将其提前msToRun 毫秒。很常见的情况是你想快进直到每个计时器都过去了,计算所有计时器完成所需的时间会很麻烦,所以 Jest 提供了jest.runAllTimers(),它假装已经过了足够的时间。

    您的测试中的问题是您从不在测试中调用jest.runAllTimers(),而是在afterAll 挂钩中调用它,该挂钩测试完成后调用。在您的测试期间,计时器保持为零,因此您的回调永远不会被实际调用,并且 Jest 在预定义的时间间隔(默认值:5 秒)后中止它,以防止陷入可能无休止的测试。只有在测试超时后,您才调用jest.runAllTimers(),此时它不会执行任何操作,因为所有测试都已完成。

    你需要做的是启动承诺,然后提前计时器。

    describe('using a promise and mock timers', () => {
        test('gets a value, if conditions favor', () => {
            expect.assertions(1)
            // Keep a reference to the pending promise.
            const pendingPromise = withPromises(true)
                .then(resolved => {
                    expect(resolved).toBe('something')
                })
            // Activate the timer (pretend the specified time has elapsed).
            jest.runAllTimers()
            // Return the promise, so Jest waits for its completion and fails the
            // test when the promise is rejected.
            return pendingPromise
        })
    })
    

    【讨论】:

    • 这行得通!非常感谢您的解释以及解释和代码示例。
    • 不错的答案!是否可以使用 async / await 语法编写此测试? ?
    猜你喜欢
    • 2021-09-20
    • 2020-04-21
    • 1970-01-01
    • 2023-03-06
    • 2021-12-26
    • 2019-09-30
    • 2021-09-15
    • 1970-01-01
    • 2021-09-15
    相关资源
    最近更新 更多