如何用Jest同时Mock默认导出类的构造函数与静态方法
解决Jest同时Mock默认导出类的构造函数与静态单例方法的问题
错误原因
你当前的Mock代码把MyClass的默认导出设成了普通对象,但实际MyClass是可被new调用的构造函数(类),因此会触发MyClass.default is not a constructor报错。要同时Mock构造函数和静态getInstance方法,必须让Mock的默认导出是可被实例化的构造函数,同时挂载静态方法,且保证构造函数返回的实例与getInstance返回的单例一致。
正确的Mock实现
import MyClass from 'path/to/MyClass'; jest.mock('path/to/MyClass', () => { // 1. 定义模拟实例,包含所有需要Mock的实例方法 const mockInstance = { methodA: jest.fn(), setData: jest.fn() }; // 2. 创建模拟构造函数,new时返回预定义的mock实例 const MockMyClass = jest.fn(() => mockInstance); // 3. 给构造函数挂载静态方法getInstance,返回同一个mock实例 MockMyClass.getInstance = jest.fn(() => mockInstance); // 4. 按ES模块规范导出 return { __esModule: true, default: MockMyClass }; }); describe('SystemUnderTest', () => { beforeEach(() => { // 每次测试前重置mock调用记录,避免测试间干扰 jest.clearAllMocks(); }); it('测试直接实例化场景', () => { const instance = new MyClass(); // 验证构造函数被调用 expect(MyClass).toHaveBeenCalled(); // 验证实例为预定义的mock对象 expect(instance.methodA).toBeDefined(); // 调用实例方法并验证mock触发 instance.methodA(); expect(instance.methodA).toHaveBeenCalled(); }); it('测试单例实例场景', () => { const instance1 = MyClass.getInstance(); const instance2 = MyClass.getInstance(); // 验证getInstance被调用两次 expect(MyClass.getInstance).toHaveBeenCalledTimes(2); // 验证两次返回同一实例 expect(instance1).toBe(instance2); // 调用实例方法验证mock instance1.setData('test'); expect(instance1.setData).toHaveBeenCalledWith('test'); }); });
关键细节说明
- 模拟构造函数:用
jest.fn(() => mockInstance)创建的函数可被new调用,调用后返回预定义的mock实例,确保new MyClass()与MyClass.getInstance()拿到同一对象,匹配原类的单例逻辑。 - 静态方法挂载:直接给模拟构造函数挂载
getInstance静态方法,保证与原类结构完全对齐。 - Mock重置:在
beforeEach中调用jest.clearAllMocks(),清空mock调用记录,避免不同测试用例互相影响。
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

