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

Jest路由测试随机出现Socket hang up错误如何排查解决?

问题核心原因

  • supertest使用逻辑冲突:你在beforeEach中手动调用serverApp.listen()启动服务,后续用supertest发请求时却传入了serverApp而非已启动的server实例。supertest传入app实例时会自动管理服务的启动/关闭,和你手动的listen/close逻辑完全冲突,会出现前一个测试的服务提前关闭、请求还未处理完成就断开连接的情况。这也刚好符合你观察到的「错误总是出现在每个describe块的第二个测试用例」的规律:第一个测试运行时服务刚启动无冲突,第二个测试运行时前一个服务的关闭逻辑还未执行完成,新老服务的连接管理出现冲突,直接触发socket hang up。
  • 异步处理模式混用:/actions的第一个测试用例同时使用了async/await和done回调两种异步判定方式,Jest的异步调度会出现混乱,可能在请求未完成时就判定测试结束,触发afterEach的服务关闭逻辑,导致正在处理的请求被强制断开。
  • Mock未正确恢复:你在第二个测试用例中重写了getProduct、getActions的Mock实现,但afterEach中只调用了jest.clearAllMocks()(仅清空调用记录,不会恢复原始实现),导致后续测试的Mock实现不符合预期,可能触发服务端未捕获的异常,提前断开请求连接。

修复步骤

  1. 统一supertest的使用逻辑,二选一即可:
    • 方案一:移除手动的服务管理逻辑,删除beforeEach、afterEach中的server.listen()和server.close()代码,直接保留request(serverApp)的调用,supertest会自动处理端口和服务生命周期
    • 方案二:保留手动服务管理,把所有request(serverApp)改为request(server),使用你手动启动的服务实例发请求
  2. 清理异步逻辑:移除/actions第一个测试用例的done参数和done()调用,仅保留async/await即可
  3. 修正Mock恢复逻辑:把afterEach中的jest.clearAllMocks()改为jest.restoreAllMocks(),确保每个测试用例运行前Mock都是初始状态
  4. 可选优化:如果仍偶发问题,可以把server.close()转为Promise等待关闭完成,确保下一次测试启动前端口已完全释放:
afterEach(async () => {
  jest.restoreAllMocks();
  await new Promise(resolve => server.close(resolve));
});

内容的提问来源于stack exchange,提问作者Antoine Deloy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:15:02