如何用Jest与react-testing-library测试React WebSocket客户端?
没问题,用jest-websocket-mock完全可以实现只模拟WebSocket服务器、让真实客户端组件连接的测试方案,不需要额外mock客户端的WebSocket实例。下面是具体的实现步骤和测试代码:
步骤1:安装依赖
首先确保你已经安装了jest-websocket-mock:
npm install --save-dev jest-websocket-mock
步骤2:编写测试用例
假设你的测试文件是LiveChat.test.jsx,我们可以这样写测试逻辑:
import React from 'react'; import { render, waitFor } from '@testing-library/react'; import MockServer from 'jest-websocket-mock'; import LiveChat from './LiveChat'; // 替换成你实际项目中TEXT常量的定义 const TEXT = 'text'; describe('LiveChat WebSocket Message Handling', () => { let mockWsServer; beforeEach(() => { // 创建一个mock服务器,使用组件中硬编码的WebSocket地址 mockWsServer = new MockServer('ws://localhost:1234'); // Mock全局的alert函数,方便我们断言它的调用情况 window.alert = jest.fn(); // 如果你的playChatMessageSound函数需要测试,也可以在这里mock它 // jest.mock('./utils/sound', () => ({ playChatMessageSound: jest.fn() })); }); afterEach(() => { // 清理mock服务器和所有jest mock MockServer.clean(); jest.restoreAllMocks(); }); it('triggers alert with correct content when receiving TEXT type message', async () => { // 渲染LiveChat组件,它会自动尝试连接到我们创建的mock服务器 render(<LiveChat />); // 等待组件和mock服务器建立连接 await mockWsServer.connected; // 模拟服务器向客户端发送TEXT类型的消息 const testPayload = { messageContent: 'Hi there! This is a test message.', messageType: TEXT, secureKey: 'test-secure-key' }; mockWsServer.send(JSON.stringify(testPayload)); // 等待alert被调用,并断言它的参数是否正确 await waitFor(() => { expect(window.alert).toHaveBeenCalledWith('Hi there! This is a test message.'); // 如果mock了playChatMessageSound,也可以加这句断言 // expect(playChatMessageSound).toHaveBeenCalled(); }); }); });
关键说明
- 不需要mock客户端WebSocket:这里我们没有修改组件里的
new WebSocket()逻辑,jest-websocket-mock会自动拦截指向目标地址的WebSocket连接,让组件连接到我们的mock服务器,完全保留客户端的真实行为。 - 等待连接建立:用
await mockWsServer.connected确保组件已经和mock服务器完成握手,避免发送消息时组件还没连接上。 - Mock全局alert:因为浏览器的alert会阻塞测试,所以我们用jest mock替换它,方便后续断言。
可选优化:让WebSocket地址可配置
如果不想依赖硬编码的WebSocket地址,可以把地址改成组件的props,这样测试时更灵活:
// 修改LiveChat组件 const LiveChat = ({ wsUrl = 'ws://localhost:1234' }) => { const [socket, setSocket] = useState(null) useEffect(() => { setSocket(new WebSocket(wsUrl)) }, [wsUrl]) // 其余代码不变 }
然后测试时传入mock服务器的地址:
render(<LiveChat wsUrl={mockWsServer.url} />);
这样不管mock服务器用什么地址,组件都能正确连接,不需要和硬编码地址强绑定。
内容的提问来源于stack exchange,提问作者onuriltan
相关产品推荐
相关产品推荐

