Angular中如何测试私有属性Socket的on方法是否被调用
验证SocketService中initializeSocket方法的socket.on调用情况
下面提供两种实用的测试方案,无需直接访问私有属性即可完成验证:
方案1:通过依赖注入解耦,便于Mock测试
原代码中Socket实例是内部创建的,不利于测试。可以修改类的构造函数,允许注入Socket的创建逻辑(工厂函数),这样测试时能传入Mock的Socket实例:
修改后的类代码:
import {Socket} from 'socket.io-client'; // 定义Socket工厂类型 type SocketFactory = () => Socket; export class SocketService { private socket: Socket; private readonly socketFactory: SocketFactory; // 注入Socket工厂,默认使用实际创建逻辑 constructor(socketFactory: SocketFactory = () => { /* 原创建Socket的逻辑 */ }) { this.socketFactory = socketFactory; } public initializeSocket() { if(this.socket) { return; } this.socket = this.socketFactory(); this.socket.on('connect', () => this.processConnect() ); } private processConnect() { // ... } }
测试代码(以Jest为例):
import { SocketService } from './socket.service'; import { Socket } from 'socket.io-client'; describe('SocketService', () => { it('should call socket.on with "connect" event when initializeSocket is called', () => { // 创建Mock的Socket实例 const mockSocket = { on: jest.fn() } as unknown as Socket; // 传入返回mockSocket的工厂函数,创建服务实例 const service = new SocketService(() => mockSocket); service.initializeSocket(); // 验证on方法的调用参数和次数 expect(mockSocket.on).toHaveBeenCalledWith('connect', expect.any(Function)); }); it('should not call socket.on again if socket already exists', () => { const mockSocket = { on: jest.fn() } as unknown as Socket; const service = new SocketService(() => mockSocket); service.initializeSocket(); service.initializeSocket(); // 第二次调用 // 验证on方法仅被调用一次 expect(mockSocket.on).toHaveBeenCalledTimes(1); }); });
方案2:直接Mock socket.io-client模块
如果不想修改原类结构,可以通过测试框架Mock整个socket.io-client模块,跟踪Socket类的实例方法调用:
测试代码(Jest为例):
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 })) }; }); describe('SocketService', () => { it('should call socket.on with "connect" event', () => { const service = new SocketService(); service.initializeSocket(); // 获取Mock的Socket实例,验证on方法调用 const mockSocketInstance = (Socket as jest.Mock).mock.instances[0]; expect(mockSocketInstance.on).toHaveBeenCalledWith('connect', expect.any(Function)); }); });
注意事项
- 无需直接访问私有属性
this.socket,通过Mock依赖的方式即可完成验证,符合黑盒测试原则。 - 若使用Vitest,只需将
jest.fn()替换为vi.fn(),jest.mock()替换为vi.mock()即可。
内容的提问来源于stack exchange,提问作者Kerwen
相关产品推荐
相关产品推荐

