Vitest测试axios调用时未加载模拟环境变量问题排查
问题分析与解决方案
你的问题大概率是以下几个原因导致的,对应解决方案如下:
1. 模块导入顺序错误
如果在调用vi.stubEnv之前就导入了getData模块,模块加载时会直接读取真实的环境变量值,后续的stubEnv无法修改已加载模块中已经缓存的变量。
错误示例:
import { getData } from './getData'; import { vi, test, expect } from 'vitest'; test('测试getData', async () => { vi.stubEnv('VITE_KEY', 'test-key'); vi.stubEnv('VITE_URL', 'test-url'); const res = await getData(); // 这里依然使用真实环境变量 });
解决方法:
将vi.stubEnv放在模块导入之前,或者使用动态导入确保环境变量模拟生效后再加载模块:
import { vi, test, expect } from 'vitest'; test('测试getData', async () => { vi.stubEnv('VITE_KEY', 'test-key'); vi.stubEnv('VITE_URL', 'test-url'); // 动态导入模块 const { getData } = await import('./getData'); const res = await getData(); // 此时使用的是模拟的环境变量 });
2. Vite环境变量预编译导致硬编码
Vite在构建阶段会将import.meta.env中的变量直接替换为实际值,即使在测试环境,如果Vitest配置未禁用该特性,会导致变量被硬编码到代码中,vi.stubEnv无法覆盖。
解决方法:
在vitest.config.ts中启用环境变量模拟,避免预编译替换:
import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { env: { mock: true, // 强制使用Vitest的环境变量模拟,跳过Vite的预替换 }, }, });
3. 函数内部缓存了环境变量值
如果getData函数提前将import.meta.env的变量赋值给了常量,后续请求会一直使用这个缓存的真实值,不会响应vi.stubEnv的修改。
错误示例:
// getData.ts import axios from 'axios'; // 模块加载时就缓存了真实环境变量 const API_KEY = import.meta.env.VITE_KEY; const BASE_URL = import.meta.env.VITE_URL; export async function getData() { return axios.get(`${BASE_URL}/data`, { headers: { 'X-API-Key': API_KEY }, }); }
解决方法:
每次请求时直接读取import.meta.env,或者将变量封装为动态获取的函数:
// 方案1:直接动态读取 export async function getData() { return axios.get(`${import.meta.env.VITE_URL}/data`, { headers: { 'X-API-Key': import.meta.env.VITE_KEY }, }); } // 方案2:封装为动态函数(适合需要复用的场景) const getApiKey = () => import.meta.env.VITE_KEY; const getBaseUrl = () => import.meta.env.VITE_URL; export async function getData() { return axios.get(`${getBaseUrl()}/data`, { headers: { 'X-API-Key': getApiKey() }, }); }
4. vi.stubEnv的作用域问题
如果vi.stubEnv是在describe或it块之外调用,但模块导入在更靠前的位置,同样会导致模块加载时读取真实变量。确保stubEnv在模块加载前执行,或者在beforeAll/beforeEach中调用并配合动态导入。
内容的提问来源于stack exchange,提问作者gespinha
相关产品推荐
相关产品推荐

