JestJS中创建多个WebSocket连接导致测试进程挂起的问题求助
问题原因
1. 核心代码逻辑错误
你提供的closeAllConnections函数存在明显的循环条件错误:
// 错误写法:直接拿数组对象和数值比较,转布尔值后永远为false for (let i = 0; i < clients; i++) {
正确的判断条件应该是i < clients.length,这个错误导致所有WebSocket连接在逻辑执行完成后都没有被正常关闭。Jest运行测试时会等待所有活跃的异步资源(包括未关闭的网络连接)释放后才会退出进程,这是导致测试挂起的最直接原因。
2. 缺失异常&兜底逻辑
你当前的代码只处理了onmessage和onerror事件,没有处理WebSocket连接超时、连接断开等异常场景,一旦服务端没有返回gameStarted事件,整个Promise会永远处于pending状态,也会导致测试挂起。
3. Jest运行环境差异
浏览器环境内置了原生WebSocket实现,但Jest默认的jsdom测试环境并没有内置WebSocket的支持,如果你没有手动配置WebSocket polyfill/模拟实现,也可能导致逻辑异常。
解决方案
第一步:修复核心逻辑错误
调整closeAllConnections的循环条件,同时补充超时兜底、缺失的事件处理逻辑,修改后的代码如下:
function checkGameStart(numberOfBots, timeout = 10000) { return new Promise((resolve, reject) => { // 增加超时兜底 const timer = setTimeout(() => { closeAllConnections(); reject(new Error('Check game start timeout')); }, timeout); let clients = []; let connection = []; for (let i = 0; i < numberOfBots; i++) { clients.push(new WebSocket('ws://127.0.0.1:8080')); connection.push(false); clients[i].onopen = () => { // 可选:如果需要建立连接后发送请求可以加在这里 }; clients[i].onmessage = (msg) => { let data = JSON.parse(msg.data); if (data.title === "gameStarted") { connection[i] = true; checkAllClientsReady(); } }; clients[i].onerror = (err) => { clearTimeout(timer); closeAllConnections(); reject(err); }; clients[i].onclose = () => { // 可选:处理连接意外断开的场景 }; } function checkAllClientsReady() { if (!connection.includes(false)) { clearTimeout(timer); resolve(true); closeAllConnections(); } } function closeAllConnections() { // 修复循环条件 for (let i = 0; i < clients.length; i++) { clients[i].close(); } } }); }
第二步:配置Jest环境支持WebSocket
- 如果使用jsdom环境,可以安装
ws库,在测试文件开头手动挂载WebSocket到全局:
import WebSocket from 'ws'; global.WebSocket = WebSocket;
- 如果需要模拟WebSocket逻辑避免调用真实服务,可以使用
jest-websocket-mock类库做模拟处理。
第三步:调整测试代码配置超时
可以在测试函数第三个参数显式指定超时时间,避免测试长时间阻塞:
test('Check the game starts', () => { return expect(checkGameStart(4)).resolves.toBe(true); }, 15000); // 超时时间设置为15秒,大于checkGameStart的默认超时即可
内容的提问来源于stack exchange,提问作者Joy Singh
相关产品推荐
相关产品推荐

