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

如何自动Mock TypeScript类实例,为测试提供依赖注入?

自动化创建Mock的实用方案

一、修正jest.mock用法,解决类实例Mock问题

你之前用jest.mock仅Mock了类的构造函数,未处理实例方法。可以通过两种方式修正:

1. 类型断言+自动Mock模块

先自动Mock整个模块,再通过类型断言让TypeScript识别Mock后的类实例方法:

// 自动Mock GameService所在的模块
jest.mock('path/to/GameService');

// 将类断言为MockedClass,使TS识别实例方法为jest.fn()
const GameServiceMock = GameService as jest.MockedClass<typeof GameService>;

// 创建实例,此时所有方法均为预设的jest.fn()
const gameService = new GameServiceMock();

2. 自定义Mock工厂函数

如果需要默认给实例方法生成Mock,可在jest.mock中传入工厂函数,返回带实例方法Mock的构造函数:

jest.mock('path/to/GameService', () => ({
  GameService: jest.fn().mockImplementation(() => ({
    someMethod: jest.fn(),
    anotherMethod: jest.fn()
  }))
}));

这样每次new GameService()都会得到带Mock方法的实例,无需手动创建Mock对象。

二、第三方工具自动生成Mock(类/接口通用,零维护)

推荐两个开箱即用的工具,可直接从TypeScript类型自动生成Mock,完全无需手动维护方法列表:

1. jest-mock-extended(轻量易用)

安装后,直接用mock函数生成任意类型的Mock实例:

import { mock } from 'jest-mock-extended';

// 生成接口的Mock实例
const gameRepoMock = mock<GameFeaturesRepository>();
// 生成类的Mock实例(无需new,直接得到带所有方法的jest.fn())
const gameServiceMock = mock<GameService>();

// 直接传入被测试类的构造函数
const gameFeaturesService = new GameFeaturesService(appContextMock, gameRepoMock, gameServiceMock);

后续修改类或接口结构时,Mock会自动同步。还可直接设置返回值或断言调用:

gameServiceMock.someMethod.mockReturnValue('mock-result');
expect(gameServiceMock.anotherMethod).toHaveBeenCalledWith('test-param');

2. automock(自动处理依赖链)

如果服务依赖链复杂,automock能自动解析构造函数的依赖,直接生成被测试类的实例,连依赖Mock都无需手动创建:

import { createMock } from '@automock/jest';

// 自动生成GameFeaturesService实例,以及所有依赖的Mock
const { unit: gameFeaturesService, refs } = createMock(GameFeaturesService);

// 如需操作某个依赖的Mock,直接通过refs获取
const gameServiceMock = refs.get(GameService);
gameServiceMock.someMethod.mockResolvedValue('async-result');

三、无依赖手动优化方案

如果不想引入第三方库,可写一个通用Mock生成函数,利用TypeScript类型自动生成方法Mock:

function createMock<T>(): jest.Mocked<T> {
  const mockObj = {} as jest.Mocked<T>;
  // 遍历类型属性,自动生成jest.fn()(仅支持公共可枚举方法)
  Object.keys(mockObj as unknown as Record<string, unknown>).forEach(key => {
    (mockObj as Record<string, unknown>)[key] = jest.fn();
  });
  return mockObj;
}

// 使用示例
const gameServiceMock = createMock<GameService>();

该方案适合简单场景,局限性是无法处理私有方法、嵌套对象等复杂结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:18:29