如何自动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
相关产品推荐
相关产品推荐

