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

如何在Cypress中使用mock-socket模拟Apollo的GraphQL subscription?

原因说明

你现有代码不生效的核心原因是:Apollo的WebSocketLink默认使用的WebSocket构造函数没有绑定到全局window对象,打包后的Apollo代码会直接引用模块作用域内的WebSocket实例,你对全局window.WebSocket的stub无法覆盖到这个内部引用。

可选解决方案

方案1:应用代码预留注入入口(最稳定,推荐)

Apollo的WebSocketLink构造参数原生支持自定义webSocketImpl,你可以在应用的Apollo Client初始化逻辑中增加测试场景的兼容逻辑:

// 应用内Apollo Client初始化代码
import { WebSocketLink } from "@apollo/client/link/ws";

const wsLink = new WebSocketLink({
  uri: "ws://你的GraphQL订阅端点地址",
  options: { reconnect: true },
  // 测试环境下优先使用Cypress注入的mock WebSocket实现
  webSocketImpl: window.CYPRESS_MOCK_WEBSOCKET || WebSocket,
});

对应的Cypress测试代码调整为:

import { Server, WebSocket as MockWebSocket } from 'mock-socket';

it('测试GraphQL订阅逻辑', () => {
  let mockServer;
  const WS_ENDPOINT = 'ws://你的GraphQL订阅端点地址';

  cy.visit('/', {
    onBeforeLoad(window) {
      // 注入mock的WebSocket实现供Apollo使用
      window.CYPRESS_MOCK_WEBSOCKET = MockWebSocket;
      // 启动mock socket服务
      if(mockServer) mockServer.stop();
      mockServer = new Server(WS_ENDPOINT);

      mockServer.on('connection', (socket) => {
        // 监听客户端请求,返回对应mock订阅数据
        socket.on('message', (rawData) => {
          const req = JSON.parse(rawData);
          // 匹配对应的订阅操作返回mock数据,示例适配subscriptions-transport-ws协议
          if(req.type === 'start' && req.payload.operationName === '你要测试的订阅操作名') {
            socket.send(JSON.stringify({
              type: 'data',
              id: req.id,
              payload: {
                data: {
                  // 你的mock返回数据
                }
              }
            }))
          }
        })
      })
    }
  })

  // 后续测试断言逻辑
})

方案2:无需修改应用代码,stub WebSocketLink构造函数

如果无法修改应用代码,你可以在onBeforeLoad阶段拦截WebSocketLink的构造逻辑,强制替换它的webSocketImpl参数:

  • 若你的应用将Apollo相关依赖挂载到了全局window对象,直接stub对应路径下的WebSocketLink构造函数即可
  • 若应用是闭包打包的,你可以通过Cypress的cy.intercept拦截加载Apollo相关JS包的请求,在返回的代码末尾注入stub逻辑,覆盖WebSocketLink的默认行为

方案3:使用Cypress原生WebSocket拦截

Cypress v12+ 已支持实验性的原生WebSocket拦截能力,开启experimentalWebsocketsSupport配置后,可直接用cy.intercept匹配WebSocket连接,模拟返回数据,无需引入第三方mock库。

注意事项
  • 如果你使用的是graphql-ws库实现的GraphQL over WebSocket新协议,需要调整mock返回的消息格式与新协议规范对齐,否则Apollo无法正常识别返回内容
  • mock-socket的服务端点必须和应用内使用的订阅端点完全一致(协议、域名、端口、路径均相同)才能匹配到请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 05:06:03