Jest在Travis-CI中检测到Redis客户端未关闭及连接方法缺失问题
问题排查与解决方案
问题1:redisClient.connect 不是函数
根因
Node Redis 包存在版本不兼容:
- 本地安装的是4.x及以上版本,该版本引入了
connect()异步方法,配置项也采用socket层级结构 - Travis CI 环境因node_modules缓存、未指定版本安装redis,实际拉取到的是3.x及以下版本,该版本客户端没有
connect()方法,创建客户端时会自动发起连接,配置结构也和4.x版本不通用
解决步骤
- 清理Travis项目的node_modules缓存,避免旧版本包残留
- 修改
.travis.yml的install步骤,指定安装和本地一致的redis兼容版本,示例:install: - npm i - npm i redis@4.6.7 # 替换为你本地实际使用的redis版本号即可 - 可在install步骤新增
npm list redis命令打印实际安装的redis版本,方便后续排查确认
问题2:Jest检测到开放TCP句柄无法退出
根因
两种场景都会触发该问题:
- 若Travis环境安装的是3.x版本redis,创建客户端时就会自动发起TCP连接,哪怕连接失败,底层socket句柄也不会自动销毁,会一直挂载在事件循环中
- 就算使用4.x版本,你当前的代码只捕获了连接异常,没有主动销毁不可用的客户端,残留的重连逻辑也会持续持有句柄
解决步骤
- 先按问题1的方案固定redis版本,消除环境版本差异
- 修改Redis初始化逻辑,连接失败时主动销毁客户端:
async function getClient() { const redisClient = createClient({ socket: { url: redisConfig.connectionString, reconnectStrategy: (currentNumberOfRetries: number) => { if (currentNumberOfRetries > 1) { // 重连超限后返回false停止重连,不要直接抛错 return false; } return 1000; }, }, }); try { await redisClient.connect(); } catch (e) { console.log(e); // 连接失败主动断开销毁客户端,释放句柄 await redisClient.quit().catch(() => redisClient.disconnect()); throw e; // 向上抛出错误,避免上层拿到不可用的客户端实例 } return redisClient; }
- 在Jest测试集的
afterAll钩子中,主动关闭所有持有的Redis连接:
afterAll(async () => { if (redisClientInstance) { // 替换为你实际持有的redis客户端变量 await redisClientInstance.quit().catch(() => redisClientInstance.disconnect()); } })
- 临时兼容方案:如果仅需要CI快速跑通测试,可在jest启动命令后添加
--forceExit参数,强制Jest测试完成后退出进程,该方案更推荐仅作为临时兜底使用。
内容的提问来源于stack exchange,提问作者Jia Cheng Sun
相关产品推荐
相关产品推荐

