如何在测试中模拟B类中实例化的外部Session类?
问题场景
现有以下TypeScript文件结构:
// A.ts export abstract class A { protected abstract method1(arg); } // Session.ts(外部类) export class Session { constructor(socket: WebSocket) { this._socket = socket; this._socket.on('close', () => { /* 业务逻辑 */ }); this._socket.on('error', () => { /* 业务逻辑 */ }); this._socket.on('message', () => { /* 业务逻辑 */ }); } setSomeSocket(someSocket: WebSocket) { this._anotherSocket = someSocket; this._anotherSocket.on('close', () => { /* 业务逻辑 */ }); this._anotherSocket.on('error', () => { /* 业务逻辑 */ }); }; } // B.ts export class B extends A { protected async method1(arg) { try { let tempSession = new Session(socket); tempSession.setSomeSocket(socket); // 其他业务逻辑 } catch(exception) { // 异常处理 } } } // B.spec.ts(原测试文件) describe("B test", () => { it("some test", async () => { const varB = new B(); await varB["method1"](arg); expect(spied).toBeCalledTimes(1); }); })
需求:在B.spec.ts中模拟外部的Session类,避免其内部的socket.on()操作引发测试问题,确保B的method1调用的是模拟后的Session实例。
解决方案(基于Jest测试框架)
1. 模拟Session模块
在测试文件顶部,通过Jest的jest.mock()方法完全替换原Session模块的导出,替换为自定义的模拟类。
2. 定义模拟类逻辑
模拟的Session类保留原类的构造函数和setSomeSocket方法,但移除所有WebSocket事件绑定逻辑,避免测试时触发不必要的操作,同时用jest.fn()包裹方法以便后续验证。
3. 验证模拟效果
通过Jest的断言方法,验证B的method1是否正确调用了Session的构造函数和相关方法。
修改后的B.spec.ts代码如下:
// B.spec.ts import { B } from './B'; // 模拟Session模块,替换为自定义实现 jest.mock('./Session', () => { return { Session: jest.fn().mockImplementation(() => { return { setSomeSocket: jest.fn() // 模拟setSomeSocket方法,空实现 }; }) }; }); // 导入模拟后的Session类 import { Session } from './Session'; describe("B test", () => { it("some test", async () => { const varB = new B(); // 执行测试方法 await varB["method1"](/* 传入测试用的arg参数 */); // 验证Session构造函数是否被调用 expect(Session).toHaveBeenCalledTimes(1); // 验证setSomeSocket方法是否被调用 const mockSessionInstance = Session.mock.results[0].value; expect(mockSessionInstance.setSomeSocket).toHaveBeenCalledTimes(1); }); })
说明
jest.mock('./Session', ...)会覆盖原模块的导出,确保B在测试时使用的是模拟类而非真实的Session。- 若需要模拟方法的返回值或特定逻辑,可以在
mockImplementation中自定义逻辑。 - 通过
jest.fn()生成的模拟函数,支持验证调用次数、传入参数等断言操作。
内容的提问来源于stack exchange,提问作者Saurav Likhar
相关产品推荐
相关产品推荐

