如何让Jest在导入的常量模块中使用process.env
问题根源
你的问题出在ES模块的静态导入机制——所有import语句会在代码执行前优先加载,所以你在测试文件里先调用dotenv.config()再导入config根本没用,config模块早就在dotenv加载环境变量之前就执行并初始化了,自然拿不到.env里的值。
解决方案
方案一:用Jest前置配置自动加载dotenv
在你的jest-e2e.json(或jest.config.js)中添加setupFiles配置,让Jest在加载任何测试代码前先执行dotenv的配置:
// jest-e2e.json { "setupFiles": ["dotenv/config"] }
如果需要指定自定义路径的.env文件,可以先写一个前置脚本:
// test/setup-dotenv.js require('dotenv').config({ path: '.env' });
然后在Jest配置中指定这个脚本:
{ "setupFiles": ["./test/setup-dotenv.js"] }
这样Jest启动时会先加载环境变量,之后所有导入的模块(包括你的config)都能读取到正确的值。
方案二:改用动态导入加载config
如果不想修改Jest全局配置,可以把config的导入改成动态导入,确保在dotenv.config()执行之后再加载模块:
import {Test, TestingModule} from "@nestjs/testing"; import {INestApplication} from "@nestjs/common"; import * as request from "supertest"; import {AppModule} from "./../src/app.module"; import * as dotenv from "dotenv"; dotenv.config({path: ".env"}); // 用动态导入确保环境变量加载完成后再获取config (async () => { const { config } = await import("../src/infrastructure/config/config"); console.log(config); // 现在能拿到.env里的值了 // 后续测试逻辑放在此异步函数内 const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); const app: INestApplication = moduleFixture.createNestApplication(); await app.init(); // ... 编写测试用例 })();
方案三:把config改成动态函数(长期推荐)
将静态的config对象改成一个函数,每次调用时才读取环境变量,这样不管模块何时加载,都能拿到最新的环境变量:
// src/infrastructure/config/config.ts export const getConfig = (): Config => ({ isProd: process.env.NODE_ENV === 'production', connection: { port: parseInt(process.env.APP_PORT) || 2000, }, });
测试文件中在dotenv.config()之后调用函数:
import { getConfig } from "../src/infrastructure/config/config"; // 确保环境变量加载完成后调用 const config = getConfig(); console.log(config);
内容的提问来源于stack exchange,提问作者Александр Евсиков
相关产品推荐
相关产品推荐

