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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:23:10