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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:24:03