如何在Jest单元测试中Mock动态变更的TypeScript枚举?
如何在TypeScript单元测试中Mock动态变化的枚举
问题背景
我有一个TypeScript枚举,其中START和END的值固定不变,但中间的枚举项会随业务需求新增或移除,用来展示新功能:
enum OriginalEnum { START = 'start', EXPORT = 'export', SEARCH = 'search', END = 'end' }
我需要测试依赖这个枚举的类,确保它能正确在枚举值间切换,但不想每次中间枚举项变化时都修改单元测试。计划用下面的Mock枚举来替代:
enum MockedEnum { START = 'start', NAME_OF_FIRST = 'nameOfFirst', NAME_OF_SECOND = 'nameOfSecond', END = 'end' }
实现方案
1. 模块级Mock(Jest/Vitest通用)
如果枚举是单独导出的模块(比如enums.ts),可以直接Mock整个模块,让依赖它的类在测试时使用Mock枚举:
原始枚举文件 enums.ts
export enum OriginalEnum { START = 'start', EXPORT = 'export', SEARCH = 'search', END = 'end' }
测试文件中Mock枚举
import { OriginalEnum } from './enums'; import { MyClass } from './my-class'; // 替换原始枚举为Mock实现 jest.mock('./enums', () => ({ OriginalEnum: { START: 'start', NAME_OF_FIRST: 'nameOfFirst', NAME_OF_SECOND: 'nameOfSecond', END: 'end' } })); describe('MyClass', () => { it('能正确在枚举值间切换', () => { const instance = new MyClass(); instance.setState(OriginalEnum.START); expect(instance.currentState).toBe(OriginalEnum.START); instance.setState(OriginalEnum.NAME_OF_FIRST); expect(instance.currentState).toBe(OriginalEnum.NAME_OF_FIRST); instance.setState(OriginalEnum.END); expect(instance.currentState).toBe(OriginalEnum.END); }); });
2. 解决TypeScript类型报错
直接Mock可能会触发类型检查错误,因为Mock枚举的键和原始枚举不匹配。可以通过类型断言或定义兼容类型来处理:
// 定义兼容类型:保留原始枚举的固定项,允许任意其他字符串键 type OriginalEnumCompatible = Pick<typeof OriginalEnum, 'START' | 'END'> & Record<string, string>; jest.mock('./enums', () => ({ OriginalEnum: { START: 'start', NAME_OF_FIRST: 'nameOfFirst', NAME_OF_SECOND: 'nameOfSecond', END: 'end' } as OriginalEnumCompatible }));
3. 优雅的类型兼容方案(推荐)
把固定的START和END提取成单独的常量,让原始枚举和Mock枚举都基于这个基础,从根源避免类型问题:
固定项定义
// constants/enum-fixed.ts export const FixedEnum = { START: 'start' as const, END: 'end' as const };
原始枚举
import { FixedEnum } from './constants/enum-fixed'; export enum OriginalEnum { START = FixedEnum.START, EXPORT = 'export', SEARCH = 'search', END = FixedEnum.END }
Mock枚举
import { FixedEnum } from './constants/enum-fixed'; export enum MockedEnum { START = FixedEnum.START, NAME_OF_FIRST = 'nameOfFirst', NAME_OF_SECOND = 'nameOfSecond', END = FixedEnum.END }
这样即使原始枚举的中间项频繁变动,只要固定项不变,测试代码就不需要任何修改,类型兼容性也能完美保障。
内容的提问来源于stack exchange,提问作者Joos
相关产品推荐
相关产品推荐

