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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 18:57:05