如何用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); }); }); });
关键修改说明
- 静态方法mock位置修正:静态方法
func2需要直接挂载到被mock的ClassA类上,而非构造函数返回的实例对象。用(ClassA as jest.MockedClass<typeof ClassA>)做类型断言,避免TypeScript报错。 - 异步方法处理:
foo是async方法,测试时必须用await调用,确保异步逻辑执行完毕后再做断言。 - mock状态重置:用
beforeEach+jest.clearAllMocks()清空mock调用记录,防止不同测试用例之间的状态干扰。 - 类型正确性优化:替换不合法的
int类型为number,给mock函数指定泛型参数明确类型,提升代码的类型安全性。
内容的提问来源于stack exchange,提问作者jad45
相关产品推荐
相关产品推荐

