NestJS框架下Jest无法通过抛出Error的测试问题
问题分析
你的测试失败核心原因有三个:
- 错误抛出时机过早:
AppConfigurationService构造函数会直接调用_getConnectionStringFromEnvFile,该方法在配置为空时同步抛出错误。你在beforeEach中就尝试获取service实例,导致测试还没进入断言阶段就触发错误,直接终止测试。 - 错误使用异步断言:
connectionString是同步属性,你用rejects(专门用于Promise的断言)完全不适用,属于概念错误。 - 模块导入冲突:测试中同时导入了
ConfigModule.forRoot和mock的ConfigService,真实配置模块可能覆盖你的mock,导致预期行为失效。
解决方案
修正测试逻辑,针对构造函数阶段的同步错误进行捕获,同时移除不必要的模块导入:
方案1:直接实例化服务(简洁版)
跳过Nest的TestingModule,直接测试服务构造逻辑:
describe('#Fail connect', () => { it('should throw error when MONGODB_DB_URI is not provided', () => { // 模拟ConfigService,返回空的MONGODB_DB_URI const mockConfigService = { get: jest.fn((key: string) => { if (key === 'MONGODB_DB_URI') return ''; }) } as unknown as ConfigService; // 用expect包裹实例化动作,捕获同步抛出的错误 expect(() => new AppConfigurationService(mockConfigService)).toThrow( 'No connection string has been provided in the .env file.' ); }); });
方案2:使用TestingModule(保持Nest测试风格)
若希望保留Nest的TestingModule结构,需把获取实例的动作放到expect中:
describe('#Fail connect', () => { it('should throw error when MONGODB_DB_URI is not provided', async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ AppConfigurationService, { provide: ConfigService, useValue: { get: jest.fn((key: string) => { if (key === 'MONGODB_DB_URI') return ''; }), }, }, ], // 移除ConfigModule导入,避免干扰mock }).compile(); // 把获取实例的动作放在expect中,捕获构造时的错误 expect(() => module.get<AppConfigurationService>(AppConfigurationService)).toThrow( 'No connection string has been provided in the .env file.' ); }); });
关键修改点说明
- 移除
ConfigModule.forRoot导入:避免真实配置模块加载.env文件或覆盖mock的ConfigService - 使用
expect(() => ...).toThrow():针对同步抛出的错误,必须用这种同步断言方式,不能用rejects - 延迟实例化时机:把服务实例化动作从
beforeEach移到测试用例的断言中,确保错误能被Jest捕获
内容的提问来源于stack exchange,提问作者Eduardo Moritz
相关产品推荐
相关产品推荐

