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

Cypress测试间WebSocket变量失效?握手失败问题排查

问题分析与解决方案

问题根源

你当前的代码将WebSocket实例声明在所有测试外部,属于全局变量。当运行多个测试时,所有测试会复用同一个WebSocket连接实例,导致连接状态混乱:

  • 第一个测试可能已经打开并关闭了连接,后续测试再操作该实例时,连接可能处于异常状态(如已关闭、正在连接中)
  • 服务器收到重复的连接请求或异常的握手信息,返回错误码200(通常表示HTTP请求而非WebSocket握手,属于协议错误)

修复方案

核心思路是每个测试使用独立的WebSocket实例,并确保测试前后的连接清理,避免状态交叉影响。

方案1:使用beforeEach/afterEach管理连接生命周期

describe("WebSocket测试组", () => {
  let ws;

  // 每个测试前创建全新的WebSocket连接
  beforeEach(() => {
    ws = new WebSocket(wsUrl);
  });

  // 每个测试后强制清理连接,避免残留状态
  afterEach((done) => {
    switch(ws.readyState) {
      case WebSocket.OPEN:
        ws.close();
        ws.onclose = () => done();
        break;
      case WebSocket.CONNECTING:
        ws.onclose = () => done();
        ws.close();
        break;
      default:
        done();
    }
  });

  it("向WSS发送消息", (done) => {
    ws.onopen = () => {
      ws.send(Message);
      // 可选:验证服务器响应
      ws.onmessage = (event) => {
        expect(event.data).to.equal("预期的响应内容");
        done();
      };
    };

    // 捕获连接错误,防止测试挂起
    ws.onerror = (error) => done(error);
  });

  it("关闭WSS连接", (done) => {
    ws.onopen = () => {
      ws.close();
      ws.onclose = () => {
        expect(ws.readyState).to.equal(WebSocket.CLOSED);
        done();
      };
    };

    ws.onerror = (error) => done(error);
  });
});

方案2:用Promise封装WebSocket流程(更符合Cypress异步模型)

避免使用done回调,改用Promise封装WebSocket的异步操作,让Cypress自动处理等待:

describe("WebSocket测试组", () => {
  it("向WSS发送消息", () => {
    cy.wrap(new Promise((resolve, reject) => {
      const ws = new WebSocket(wsUrl);
      
      ws.onopen = () => {
        ws.send(Message);
        ws.onmessage = (event) => {
          ws.close();
          resolve(event.data);
        };
      };

      ws.onerror = reject;
      ws.onclose = () => reject(new Error("连接未完成就关闭"));
    })).then((response) => {
      expect(response).to.equal("预期的响应内容");
    });
  });

  it("关闭WSS连接", () => {
    cy.wrap(new Promise((resolve, reject) => {
      const ws = new WebSocket(wsUrl);
      
      ws.onopen = () => {
        ws.close();
        ws.onclose = () => resolve();
      };

      ws.onerror = reject;
    })).then(() => {
      // 验证连接已关闭(可选)
    });
  });
});

关键注意事项

  • 绝对不要复用WebSocket实例:每个测试必须创建独立的连接,避免状态污染
  • 处理异常场景:添加onerror监听,防止连接失败时测试无限挂起
  • 确保清理完成:afterEach中覆盖所有可能的连接状态(打开、连接中、已关闭),保证测试环境干净

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:23:12