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

如何在Vitest的同一测试文件中多次模拟全局模块?

在Vitest中动态修改process.cwd()模拟值的实现方案

问题背景

需要在同一测试文件中多次修改process.cwd()的返回值,现有vi.mock方案只能固定返回值,尝试doMock未达预期,已配置restoreMocks: true自动恢复模拟。

解决方案

方法1:直接使用vi.spyOn动态替换(推荐)

无需提前mock整个process模块,直接在测试用例中针对cwd方法做spy并修改返回值,利用restoreMocks配置自动清理:

import process from 'process';

describe('动态模拟process.cwd', () => {
  it('模拟路径A', () => {
    vi.spyOn(process, 'cwd').mockReturnValue('/mock/path/a');
    expect(process.cwd()).toBe('/mock/path/a');
  });

  it('模拟路径B', () => {
    vi.spyOn(process, 'cwd').mockReturnValue('/mock/path/b');
    expect(process.cwd()).toBe('/mock/path/b');
  });
});

方法2:可修改变量配合vi.mock(适用于模块导入时即调用cwd的场景)

将mock的cwd方法指向一个外部可修改变量,通过改变变量值动态调整返回结果:

import process from 'process';

// 定义可修改的mock返回值变量
let mockCwdValue = '/default/mock/path';

vi.mock('process', async () => {
  const actualProcess = await vi.importActual('process');
  return {
    default: {
      ...actualProcess,
      cwd: () => mockCwdValue
    }
  };
});

describe('动态修改mock的cwd返回值', () => {
  // 每次测试前重置默认值,避免用例间污染
  beforeEach(() => {
    mockCwdValue = '/default/mock/path';
  });

  it('使用默认mock路径', () => {
    expect(process.cwd()).toBe('/default/mock/path');
  });

  it('切换为自定义测试路径', () => {
    mockCwdValue = '/custom/test/path';
    expect(process.cwd()).toBe('/custom/test/path');
  });
});

方法3:vi.doMock配合模块重置(繁琐,不推荐)

若必须使用doMock,需在每次测试前重置已加载模块,并动态导入process:

describe('使用doMock实现动态模拟', () => {
  beforeEach(async () => {
    vi.resetModules(); // 重置所有已加载模块
  });

  it('模拟路径X', async () => {
    vi.doMock('process', async () => ({
      default: {
        ...await vi.importActual('process'),
        cwd: () => '/doMock/path/x'
      }
    }));
    const { default: process } = await import('process');
    expect(process.cwd()).toBe('/doMock/path/x');
  });

  it('模拟路径Y', async () => {
    vi.doMock('process', async () => ({
      default: {
        ...await vi.importActual('process'),
        cwd: () => '/doMock/path/y'
      }
    }));
    const { default: process } = await import('process');
    expect(process.cwd()).toBe('/doMock/path/y');
  });
});

原doMock失效原因

doMock仅对后续导入的模块生效,若测试文件顶部已提前import process,则原有导入的process实例不受doMock影响,必须配合vi.resetModules()重新导入模块才能生效。

内容的提问来源于stack exchange,提问作者seancdavis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:46:23