js中无法用mock.js或msw直接mock websocket,需通过替换全局websocket构造函数实现轻量模拟;推荐手动替换或使用websocket-mock库,注意环境隔离、url分流和测试后状态清理。

JS 项目中无法用传统 Mock 工具(如 Mock.js、msw)直接拦截和模拟 WebSocket,因为 WebSocket 是底层 TCP 连接,不走 HTTP 协议栈,不能被 fetch/XHR 拦截器捕获。但可以通过替换全局 WebSocket 构造函数的方式,在运行时劫持连接行为,实现轻量、可控的模拟。
手动替换 WebSocket 构造函数
这是最直接、兼容性最好、无需额外依赖的方法。核心思路是在测试或开发环境早期,把 window.WebSocket 替换为一个自定义类,该类模拟连接、发送、接收逻辑,同时暴露控制接口(如主动推送消息、关闭连接等)。
- 在入口文件(如
main.js或测试 setup 文件)顶部尽早执行替换,确保业务代码加载前生效 - 自定义类需实现
onopen、onmessage、onclose、send()、close()等关键属性/方法 - 可维护内部状态(如是否已连接、缓存的消息队列),支持同步/异步响应
示例:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
// mock-websocket.js
class MockWebSocket {
constructor(url) {
this.url = url;
this.readyState = WebSocket.CONNECTING;
this._onopen = null;
this._onmessage = null;
this._onclose = null;
// 模拟立即连接成功(可改为 setTimeout 模拟延迟)
setTimeout(() => {
this.readyState = WebSocket.OPEN;
if (this._onopen) this._onopen({ type: 'open' });
}, 0);
}
send(data) {
// 可在此处解析 data,触发预设响应
if (data === '{"type":"ping"}') {
this._onmessage?.({ data: JSON.stringify({ type: 'pong', ts: Date.now() }) });
}
}
close() {
this.readyState = WebSocket.CLOSED;
if (this._onclose) this._onclose({ type: 'close' });
}
get onopen() { return this._onopen; }
set onopen(fn) { this._onopen = fn; }
get onmessage() { return this._onmessage; }
set onmessage(fn) { this._onmessage = fn; }
get onclose() { return this._onclose; }
set onclose(fn) { this._onclose = fn; }
}
// 替换全局 WebSocket(仅限开发/测试环境)
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
window.WebSocket = MockWebSocket;
}
使用专用库:websocket-mock
如果需要更完善的生命周期控制、事件广播、多客户端管理或与 Jest/Testing Library 集成,推荐使用 websocket-mock。它提供实例化服务端(WebSocketServer)和客户端(MockWebSocket)的能力,支持真实事件流模拟。
- 安装:
npm install websocket-mock --save-dev - 在测试 setup 中启动 mock server,并配置客户端 URL 指向它(如
ws://localhost:8080) - 测试中可通过 server 实例主动触发消息:
server.broadcast('hello')或向指定 client 发送 - 支持断开重连、错误事件(
onerror)、二进制数据等边界场景
配合 MSW 的实验性方案(有限支持)
MSW v2+ 提供了 setupWorker 的扩展能力,但其 websocket 模块目前仅支持监听真实 WebSocket 连接的事件日志(非拦截),不能伪造响应。不过社区有基于 MSW 的实验封装(如 msw-websocket),原理仍是替换构造函数 + 注册 handler。这类方案适合已重度使用 MSW 的项目,但成熟度和文档不如前两种。
- 不建议新项目为此引入复杂抽象,除非已有统一 Mock 基础设施
- 注意检查其对
binaryType、bufferedAmount、extensions等字段的支持程度
注意事项与最佳实践
无论采用哪种方式,都需注意以下几点以避免陷阱:
- 环境隔离:确保 Mock 只在开发或测试环境启用,生产环境必须使用原生 WebSocket
-
URL 匹配逻辑:若项目连接多个 ws 地址(如
wss://chat.example.com和wss://notify.example.com),可在 Mock 类中根据url参数分流处理 - 清理副作用:单元测试中每次测试后应重置 Mock 状态(如清空 message 队列、还原构造函数),防止测试间污染
- 真实感权衡:过度模拟(如精确模拟网络抖动、部分帧丢失)会增加维护成本;优先覆盖业务关键路径(如登录后自动订阅、心跳保活、异常断连重试)










