使用web3.eth.getBlock时Jest报open handle错误该如何解决?
报错触发原因
这个报错的核心原因是Web3的HttpProvider默认开启了HTTP长连接复用,底层会维持TCP连接池,测试用例执行完成后连接没有被主动释放,Jest检测到存在存活的句柄因此无法正常退出。报错指向await web3.eth.getBlock('latest')行是因为该请求是连接池初始化的触发点。
解决方案
- 方案1:测试结束后主动关闭Provider连接(最推荐)
在测试逻辑执行完成后调用Provider的销毁方法手动释放连接,修改后的示例代码如下:
var currentProvider = new Web3.providers.HttpProvider('https://ropsten.infura.io/v3/XXXXXXXXX'); var web3 = new Web3(currentProvider); const info = await web3.eth.getBlock('latest') expect(info.gasLimit).toBeGreaterThan(0) // 测试完成后销毁连接 if (currentProvider.connection) { currentProvider.connection.destroy() // 部分web3版本可替换为 currentProvider.disconnect() }
如果是多测试用例的场景,可以将销毁逻辑放在afterAll钩子中统一执行。
- 方案2:初始化Provider时禁用长连接
如果业务场景不需要复用HTTP连接,可以在创建HttpProvider时关闭keepAlive配置,请求完成后连接会自动释放,无需额外手动销毁:
var currentProvider = new Web3.providers.HttpProvider('https://ropsten.infura.io/v3/XXXXXXXXX', { keepAlive: false }); var web3 = new Web3(currentProvider);
- 方案3:配置Jest强制退出(兜底方案)
如果仅需要临时跑测不想修改业务代码,可以在启动jest命令时添加--forceExit参数,强制Jest跑完所有测试用例后直接终止进程:jest --forceExit
也可以在jest.config.js中添加全局配置永久生效:
module.exports = { // 其余配置项 forceExit: true }
注意:该方案为强制杀进程处理,可能会导致未完成的异步日志、上报等逻辑执行中断,不建议在CI流水线等正式场景使用。
内容的提问来源于stack exchange,提问作者Code Of Light
相关产品推荐
相关产品推荐

