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

如何为使用socket.io-client的SocketService类编写单元测试并Mock Socket?

如何Mock私有Socket属性并验证on方法调用

核心思路

由于Socket是类的私有属性,直接访问它不符合封装原则。我们可以通过Mock整个socket.io-client模块来模拟Socket实例,绕开私有属性的限制,进而验证on方法的调用情况。以下以Jest测试框架为例给出具体实现方案:

具体实现步骤

1. Mock socket.io-client模块

在测试文件中,Mock整个模块,返回带有模拟Socket类的对象,该类的实例包含我们需要验证的on方法:

import { SocketService } from './socket.service';
import { Socket } from 'socket.io-client';

// Mock socket.io-client模块
jest.mock('socket.io-client', () => {
  const mockOn = jest.fn();
  return {
    Socket: jest.fn().mockImplementation(() => ({
      on: mockOn,
      // 若需验证其他方法(如emit),可在此添加对应的mock函数
      // emit: jest.fn()
    }))
  };
});

2. 编写测试用例

实例化SocketService并调用目标方法,通过获取Mock实例来验证on方法的调用:

describe('SocketService', () => {
  let socketService: SocketService;
  let mockSocketInstance: jest.Mocked<Socket>;
  let mockOnMethod: jest.Mock;

  beforeEach(() => {
    jest.clearAllMocks();
    socketService = new SocketService();
    // 获取Socket构造函数生成的mock实例
    mockSocketInstance = (Socket as jest.Mock).mock.instances[0] as jest.Mocked<Socket>;
    mockOnMethod = mockSocketInstance.on as jest.Mock;
  });

  test('initializeSocket 应调用socket.on绑定connect事件', () => {
    socketService.initializeSocket();
    
    expect(mockOnMethod).toHaveBeenCalledTimes(1);
    expect(mockOnMethod).toHaveBeenCalledWith('connect', expect.any(Function));
  });

  test('initializeSocket 已初始化时不应创建新Socket', () => {
    socketService.initializeSocket();
    socketService.initializeSocket();
    
    // 验证Socket构造函数仅执行一次
    expect(Socket).toHaveBeenCalledTimes(1);
    // 验证on方法仅被调用一次
    expect(mockOnMethod).toHaveBeenCalledTimes(1);
  });
});

额外建议

  • 如果你的Socket实例是通过io()函数(而非直接new Socket)创建的,只需调整Mock对象,将Socket替换为io函数即可,核心思路保持一致。
  • 若需验证私有方法processConnect是否被触发,可手动调用connect事件的回调函数,再通过两种方式验证:
    • 方式1(不推荐,仅临时验证用):通过jest.spyOn强制访问私有方法:
      test('processConnect 应在socket连接时被调用', () => {
        socketService.initializeSocket();
        const connectCallback = mockOnMethod.mock.calls[0][1];
        // 强制spy私有方法
        const processConnectSpy = jest.spyOn(socketService as any, 'processConnect').mockImplementation(() => {});
        
        connectCallback();
        expect(processConnectSpy).toHaveBeenCalled();
      });
      
    • 方式2(推荐):验证processConnect执行后的副作用,比如它触发的其他事件、修改的状态等,避免直接访问私有方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:55:18