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

使用Jest和NestJS测试环境变量模块时遇到问题

NestJS EnvModule 环境变量校验测试失败问题解决

我用NestJS的ConfigModule结合Joi写了一个EnvModule做环境变量校验,但是编写的测试用例一直失败,找不到问题所在。模块和测试代码如下,试过在expect里创建模块也没成功。

模块代码

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import * as Joi from 'joi';

@Module({
  imports: [
    ConfigModule.forRoot({
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test')
          .default('development')
          .required(),
        PORT: Joi.number().default(5000).required(),
      }),
      isGlobal: true,
    }),
  ],
})
export class EnvModule {}

原测试代码

import { Test } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';

import { EnvModule } from './env.module';

describe('EnvModule', () => {
  let configService: ConfigService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [EnvModule],
    }).compile();

    configService = moduleRef.get<ConfigService>(ConfigService);
  });

  it('should throw an error if NODE_ENV is not one of "development", "production", or "test"', () => {
    process.env.NODE_ENV = 'invalid_env';

    expect(() => new EnvModule()).toThrowError(
      'Validation error: "NODE_ENV" must be one of [development, production, test].',
    );

    process.env.NODE_ENV = 'test';
  });
});

问题原因分析

  • 直接new EnvModule()无法触发ConfigModule的初始化逻辑:Nest模块的配置加载和校验是由Nest容器在编译模块时处理的,手动实例化模块类不会执行任何配置逻辑。
  • 环境变量修改时机错误:原测试中beforeEach提前编译了模块,此时环境变量已经完成校验,后续修改process.env不会影响已初始化的模块实例。
  • 错误捕获方式不正确:模块编译是异步操作,同步的expect(() => ...)无法捕获异步抛出的异常。

修复后的测试代码

import { Test } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';
import { EnvModule } from './env.module';

describe('EnvModule', () => {
  // 保存原始环境变量,测试后恢复,避免影响其他测试
  const originalNodeEnv = process.env.NODE_ENV;

  afterEach(() => {
    process.env.NODE_ENV = originalNodeEnv;
  });

  it('should throw an error when NODE_ENV is invalid', async () => {
    process.env.NODE_ENV = 'invalid_env';

    // 异步捕获模块编译时的校验错误
    await expect(
      Test.createTestingModule({ imports: [EnvModule] }).compile()
    ).rejects.toThrow('Validation error: "NODE_ENV" must be one of [development, production, test].');
  });

  it('should initialize successfully with valid NODE_ENV', async () => {
    process.env.NODE_ENV = 'test';

    const moduleRef = await Test.createTestingModule({ imports: [EnvModule] }).compile();
    const configService = moduleRef.get<ConfigService>(ConfigService);

    // 验证环境变量被正确读取
    expect(configService.get('NODE_ENV')).toBe('test');
    expect(configService.get('PORT')).toBe(5000);
  });
});

修复说明

  • 移除全局beforeEach,每个测试用例独立创建模块,保证环境隔离。
  • 用afterEach恢复原始环境变量,避免测试用例之间互相干扰。
  • 对错误场景使用expect.rejects.toThrow捕获异步的模块初始化异常。
  • 新增正常场景测试,验证环境变量能被正确加载和读取。

内容的提问来源于stack exchange,提问作者Radosław Łuczak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:25:10