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

如何用Jest完整模拟TypeScript类的构造函数、实例与静态方法

Jest 正确模拟类的构造函数、实例方法和静态方法的完整示例

你的测试代码失败的核心问题是静态方法func2的mock位置错误——你把它放到了mock构造函数返回的实例对象里,但静态方法是挂载在ClassA类本身的,不属于实例属性。另外还有两个小问题:TypeScript里没有int类型,要改成number;foo是异步方法,测试时必须加await,否则断言会在异步逻辑执行完前触发,导致结果不符合预期。

以下是修正后的完整代码:

ClassA.ts

export class ClassA {
  constructor() {
    // 原构造逻辑
  }

  public async func1(x: number): Promise<void> { // 替换TypeScript不支持的int类型
    // 原func1逻辑
  }

  static func2(x: string | number): x is string {
    let conditionIsMet: boolean;
    // 原conditionIsMet逻辑
    if (conditionIsMet) {
      return true;
    }
    return false;
  }
}

CodeUnderTest.ts

import { ClassA } from './ClassA';

export class ClassB {
  public async foo() {
    if (ClassA.func2('asdf')) {
      const a = new ClassA();
      await a.func1(45);
    }
  }
}

UnitTest.ts

import { ClassB } from './ClassB';
import { ClassA } from './ClassA';

// 提前定义所有mock函数并指定类型
const mockFunc1 = jest.fn<Promise<void>, [number]>();
const mockStaticFunc2 = jest.fn<boolean, [string | number]>();

// 正确构造ClassA的mock
jest.mock('./ClassA', () => {
  return {
    ClassA: jest.fn().mockImplementation(() => {
      // 实例方法挂载在构造函数返回的对象上
      return {
        func1: mockFunc1
      };
    })
  };
});

// 把静态方法挂载到mock的ClassA类本身
(ClassA as jest.MockedClass<typeof ClassA>).func2 = mockStaticFunc2;

beforeEach(() => {
  // 每次测试前重置mock,避免跨测试用例污染
  jest.clearAllMocks();
  mockStaticFunc2.mockReturnValue(true);
});

describe('ClassB.foo() 调用时', () => {
  describe('当ClassA.func2传入字符串参数时', () => {
    it('应按预期调用ClassA.func2、构造函数和func1', async () => {
      // 准备测试实例
      const clsB = new ClassB();

      // 执行异步方法(必须加await等待逻辑完成)
      await clsB.foo();

      // 断言验证
      expect(mockStaticFunc2).toHaveBeenCalledTimes(1);
      expect(mockStaticFunc2).toHaveBeenCalledWith('asdf');
      expect(ClassA).toHaveBeenCalledTimes(1);
      expect(mockFunc1).toHaveBeenCalledTimes(1);
      expect(mockFunc1).toHaveBeenCalledWith(45);
    });
  });
});

关键修改说明

  1. 静态方法mock位置修正:静态方法func2需要直接挂载到被mock的ClassA类上,而非构造函数返回的实例对象。用(ClassA as jest.MockedClass<typeof ClassA>)做类型断言,避免TypeScript报错。
  2. 异步方法处理:foo是async方法,测试时必须用await调用,确保异步逻辑执行完毕后再做断言。
  3. mock状态重置:用beforeEach+jest.clearAllMocks()清空mock调用记录,防止不同测试用例之间的状态干扰。
  4. 类型正确性优化:替换不合法的int类型为number,给mock函数指定泛型参数明确类型,提升代码的类型安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:54:49