Vitest Mock未生效:ssmClient输出真实实现而非Mock实例
Vitest中vi.mock不生效的常见原因及解决办法
1. 模块导入顺序错误
Vitest默认会将vi.mock提升到所有import语句之前,但如果在测试文件中先导入了被Mock的模块,再调用vi.mock,提升机制会失效,导致导入的是真实模块而非Mock版本。
错误示例:
// 先导入模块,vi.mock提升后也无法覆盖已导入的真实模块 import { ssmClient } from '../src/helpers/aws'; vi.mock('../src/helpers/aws', () => ({ ssmClient: vi.fn() })); test('测试ssmClient', () => { console.log(ssmClient); // 输出真实实现 });
解决办法:
确保vi.mock在所有import语句之前执行,或者使用动态导入延迟模块加载:
// 正确写法:vi.mock在import之前 vi.mock('../src/helpers/aws', () => ({ ssmClient: vi.fn() })); import { ssmClient } from '../src/helpers/aws'; test('测试ssmClient', () => { console.log(ssmClient); // 输出Mock版本 });
或动态导入:
vi.mock('../src/helpers/aws', () => ({ ssmClient: vi.fn() })); test('测试ssmClient', async () => { const { ssmClient } = await import('../src/helpers/aws'); console.log(ssmClient); // 输出Mock版本 });
2. Mock路径与实际导入路径不匹配
vi.mock的路径必须与被测代码中导入目标模块的路径完全一致(包括相对层级、大小写、别名),否则Mock不会生效。
常见场景:
- 测试文件与被测文件层级不同,相对路径计算错误:比如被测文件在
src/services/foo.ts中导入../helpers/aws,测试文件在tests/services/foo.test.ts中,Mock路径应为../../src/helpers/aws而非../src/helpers/aws。 - 使用了路径别名但未在Vitest配置中同步:如果项目用
@/helpers/aws作为别名,需在vitest.config.ts中配置别名,并在vi.mock中使用相同别名。
别名配置示例:
// vitest.config.ts import { defineConfig } from 'vitest/config'; export default defineConfig({ resolve: { alias: { '@': './src', }, }, });
Mock时使用别名:
vi.mock('@/helpers/aws', () => ({ ssmClient: vi.fn() }));
3. 未正确匹配模块的导出方式
如果目标模块使用命名导出,Mock时必须返回对应的命名成员;如果是默认导出,则需返回default字段。错误的导出匹配会导致Mock失效。
原模块示例:
// src/helpers/aws.ts import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'; // 命名导出实例和命令 export const ssmClient = new SSMClient({ region: 'us-east-1' }); export const getParameterCommand = GetParameterCommand;
正确Mock示例:
vi.mock('../src/helpers/aws', () => { // 模拟ssmClient的send方法 const mockSsmClient = { send: vi.fn().mockResolvedValue({ Parameter: { Value: 'test' } }) }; // 模拟GetParameterCommand类 const mockGetParameterCommand = vi.fn(); return { // 对应原模块的命名导出 ssmClient: mockSsmClient, getParameterCommand: mockGetParameterCommand }; });
4. Vitest配置干扰Mock提升
某些Vitest配置会影响vi.mock的自动提升机制:
- 禁用了
globals:如果未在vitest.config.ts中设置test.globals: true,需确保导入vi对象(如import { vi } from 'vitest'),且vi.mock的位置正确。 - 第三方插件或Esbuild配置:部分插件可能修改模块加载顺序,导致Mock提升失效,可尝试临时禁用插件排查。
5. 生产代码出现Mock问题的特殊情况
如果生产代码中也出现类似“使用Mock版本”的问题,大概率是:
- 误将测试用的Mock代码提交到生产分支;
- 生产代码中错误引用了测试目录下的文件;
- 构建工具配置错误,将测试Mock代码打包进生产产物。
解决办法:检查Git提交记录、生产代码的导入路径、构建工具的排除规则(确保测试目录不被打包)。
内容的提问来源于stack exchange,提问作者Abdalrahman Shatou
相关产品推荐
相关产品推荐

