mock.js 无法模拟 websocket,因其仅拦截 http 请求,不介入 websocket 底层 socket 生命周期;应使用 mock-socket 替换全局 websocket 或手写 fakewebsocket 类。
mock.js 本身不支持模拟 websocket,它只拦截 http 请求(xmlhttprequest 和 fetch),对 websocket 构造函数无感知、无法劫持。强行在代码里写 mock.mock(/ws:\/\/.*/, ...) 是无效的,运行时会直接报 websocket is not defined 或连接失败。
为什么 Mock.js 不能用于 WebSocket 模拟
根本原因在于协议层隔离:WebSocket 是独立于 HTTP 的全双工通信协议,浏览器通过原生 WebSocket 构造函数建立连接,而 Mock.js 的拦截机制只作用于请求发起阶段(即 send() 调用前的请求对象包装),不介入底层 socket 生命周期。
常见错误现象包括:
- 页面控制台报错
Failed to construct 'WebSocket': Please use the 'ws:' or 'wss:' protocol - 连接看似成功(
readyState === 1),但onmessage从不触发 -
Mock.setup()或Mock.mock()对ws://URL 完全无响应
替代方案:用 mock-socket 替代全局 WebSocket
真正可行的前端 Mock 方式是用 mock-socket 直接替换浏览器的 window.WebSocket,让所有 new WebSocket(...) 实例都指向本地模拟服务器。
实操要点:
- 安装:
npm install mock-socket --save-dev - 在测试入口或
beforeAll中提前初始化:import { Server } from 'mock-socket'; const server = new Server('ws://localhost:8080'); - 确保客户端连接地址与
Server初始化地址完全一致(协议、host、port、path) - 若需手动控制替换时机(比如仅在某些 test case 中启用),传入
{ mock: false }并显式赋值:window.WebSocket = WebSocket;
注意:mock-socket 不修改 WebSocket 原型方法,所以 ws.send()、ws.close() 等行为仍按标准语义执行,只是目标被重定向。
Socket.IO 场景下如何兼容
mock-socket 对 Socket.IO 的支持是有限的——它不实现完整 io 客户端逻辑,但能模拟服务端事件收发。关键在于手动挂载 io 对象:
- 引入:
import { SocketIO } from 'mock-socket'; - 在测试环境注入:
window.io = SocketIO; - 服务端监听需用
socket.on('xxx', ...),客户端用socket.emit('xxx', ...),不能依赖io.connect().on('connect')的自动重连逻辑 - 不支持命名空间(
/chat)、中间件、适配器等高级特性
如果你的项目重度依赖 Socket.IO 的自动降级、房间管理或广播能力,mock-socket 只能覆盖基础消息通路,建议改用真实轻量服务(如 ws + Node.js)做集成测试。
简易手写 FakeWebSocket 类(零依赖场景)
当无法引入第三方库(如 CI 环境限制、或只需极简反馈),可手写一个最小可用的 FakeWebSocket:
class FakeWebSocket {
constructor(url) {
this.url = url;
this.readyState = WebSocket.CONNECTING;
setTimeout(() => {
this.readyState = WebSocket.OPEN;
if (this.onopen) this.onopen();
// 模拟一条欢迎消息
setTimeout(() => {
if (this.onmessage) this.onmessage({ data: JSON.stringify({ type: 'welcome' }) });
}, 300);
}, 100);
}
send(data) {
console.log('[FakeWS] sent:', data);
}
close() {
this.readyState = WebSocket.CLOSING;
setTimeout(() => { this.readyState = WebSocket.CLOSED; }, 50);
}
}
window.WebSocket = FakeWebSocket;
这个类不处理事件监听器数组管理、二进制支持或错误回调,但足以让组件不崩溃,并触发 onopen 和 onmessage 流程。复杂业务逻辑仍需补全状态机和事件分发。
实际项目中,最易踩的坑不是“选哪个工具”,而是混用多种 Mock 方式导致全局 WebSocket 被多次覆盖或未清理。比如 Jest 测试中一个 test 文件启用了 mock-socket,另一个用了手写类,又没调用 server.stop(),后续测试就会收到上一个模拟服务器的残留消息。务必在 afterAll 或 teardown 阶段显式销毁实例。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











