Jest检测到open handles报错,使用bull的Node项目测试如何修复?
问题根因
Bull队列实例内部会维持和Redis服务的长连接用于任务调度、状态同步,测试执行完成后这些连接没有被主动释放,就会被Jest识别为未关闭的资源句柄,导致Jest无法正常退出。单纯的延时等待不会主动关闭这些连接,所以无法解决问题。
修复方案
方案1:主动关闭所有队列实例(最推荐)
你需要先将业务代码中实例化的队列导出,再在测试的afterAll钩子中主动调用队列的close()方法释放连接:
- 导出队列实例
// 原队列定义的文件中添加导出 export const csvExportsQueue = ['test', 'development'].includes(process.env.NODE_ENV) ? new Queue('exports') : new Queue('csv exports', 'redis://redis:6379/13');
- 在测试文件中关闭队列
import { csvExportsQueue } from './你的队列定义文件路径'; afterAll(async () => { // 关闭队列,释放Redis连接 await csvExportsQueue.close(); // 如果你有其他实例化的Bull队列,也依次调用close方法 // await otherQueue.close(); });
如果测试中存在未处理的队列任务,可以先清空队列再关闭:
afterAll(async () => { await csvExportsQueue.obliterate({ force: true }); await csvExportsQueue.close(); });
方案2:Mock Bull队列规避真实连接(单元测试推荐)
如果是单元测试场景,不需要真实调用Redis和队列逻辑,可以在Jest的全局配置文件/测试文件顶部Mock Bull库,完全规避真实网络连接的产生:
jest.mock('bull', () => { return jest.fn().mockImplementation(() => ({ add: jest.fn(), process: jest.fn(), close: jest.fn().mockResolvedValue(true), // 补充其他你业务中用到的队列方法的Mock实现 })); });
方案3:强制Jest退出(临时兜底方案)
如果不需要严格校验资源释放,也可以在Jest启动参数中添加--forceExit强制测试跑完后直接退出进程,修改package.json中的测试命令即可:
{ "scripts": { "test": "jest --forceExit" } }
注意:该方案属于兜底手段,会掩盖其他未释放资源的问题,非必要不推荐使用
内容的提问来源于stack exchange,提问作者opensource-developer
相关产品推荐
相关产品推荐

