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实现不符合预期,可能触发服务端未捕获的异常,提前断开请求连接。
修复步骤
- 统一supertest的使用逻辑,二选一即可:
- 方案一:移除手动的服务管理逻辑,删除
beforeEach、afterEach中的server.listen()和server.close()代码,直接保留request(serverApp)的调用,supertest会自动处理端口和服务生命周期 - 方案二:保留手动服务管理,把所有
request(serverApp)改为request(server),使用你手动启动的服务实例发请求
- 方案一:移除手动的服务管理逻辑,删除
- 清理异步逻辑:移除
/actions第一个测试用例的done参数和done()调用,仅保留async/await即可 - 修正Mock恢复逻辑:把
afterEach中的jest.clearAllMocks()改为jest.restoreAllMocks(),确保每个测试用例运行前Mock都是初始状态 - 可选优化:如果仍偶发问题,可以把
server.close()转为Promise等待关闭完成,确保下一次测试启动前端口已完全释放:
afterEach(async () => { jest.restoreAllMocks(); await new Promise(resolve => server.close(resolve)); });
内容的提问来源于stack exchange,提问作者Antoine Deloy
相关产品推荐
相关产品推荐

