You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest结合事件发射器的异步测试无法正常结束的问题求助

Jest结合事件发射器的异步测试无法正常结束的问题求助

我现在在测试一个Node.js进程,它的逻辑是从Redis队列读取数据、处理后把结果推送到另一个Redis队列。为了做黑盒测试,我给数据库和缓存都做了mock,核心逻辑保持不变。其中Redis的mock在往输出队列执行lpush时会触发一个事件,我本来打算在测试里捕获这个事件来做断言检查。

现在的问题是:功能本身是正常的——事件确实触发了,测试里也捕获到了,数据也正确,但测试就是没法正常结束,甚至Jest会一直挂着,哪怕用了默认的5秒超时也没用。

我试过两种写法都不行,一种用done回调,另一种用Promise+async/await,虽然断言都通过了、日志也打印了,但Jest就是不退出。我不想去mock业务逻辑里的推送函数,想保持黑盒测试的完整性,有没有大佬能给点提示?

第一种用done的测试写法

describe('foo', () => {
  describe('bar', () => {
    const fakeData = [{ id: 1 }]
    const EE = new EventEmitter()

    beforeAll(() => {
      redisMock.new = jest.fn(() => ({
        brpop: jest.fn(() => fakeData.pop()),
        lpush: jest.fn((destQueue, data) => EE.emit('lpush', { destQueue, data })),
      }))
      mylogicWhichUsesRedis.start()
    })

    test('my test', (done) => {
      EE.once('lpush', (params) => {
        console.log(params)
        expect(params.destQueue).toEqual('something')
        console.log('test') // 这里能正常打印
        done()
      })
    })
  })
})

第二种用Promise+async/await的测试写法

test('foobar', async () => {
  const params = await new Promise((resolve) => {
    EE.once('lpush', resolve)
  })
  expect(params.destQueue).toEqual('something')
  console.log('this get printed') // 这里也能正常打印
})

可能的原因分析和解决方案

我猜大概率是你的mylogicWhichUsesRedis.start()启动了一个持续运行的进程(比如轮询Redis的循环),Jest在测试完成后没法自动终止这个进程,导致一直挂着。给你几个可行的解决思路:

  • 在afterAll里停止业务进程
    给你的mylogicWhichUsesRedis加一个stop()方法,在测试结束后调用它来终止所有异步循环或连接,这是最规范的做法,能保证测试环境干净收尾:

    afterAll(() => {
      mylogicWhichUsesRedis.stop()
    })
    
  • 检查Redis mock的异步逻辑是否有残留
    实际Redis的brpop是异步阻塞操作,你的业务逻辑里可能有基于它的轮询循环。虽然mock成了同步返回,但如果循环没有在数据耗尽后停止,就会一直占用线程,导致Jest无法退出。可以检查业务逻辑的轮询终止条件,确保mock数据用完后能停止循环。

  • 兜底方案:Jest参数强制退出
    如果暂时没法修改业务逻辑,可以在运行测试时加上--forceExit参数,让Jest在测试完成后强制终止进程。但这是兜底手段,可能会掩盖潜在的资源泄漏问题,不推荐长期使用。

备注:内容来源于stack exchange,提问作者Andrea Franchini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 06:53:10