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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:52:09