NestJS测试ConfigService时Mock不生效及自定义Fake类异常问题咨询
问题原因
- 你在测试模块中同时导入了
ConfigModule和自定义的ConfigServiceMock,依赖注入出现冲突导致Mock没有实际生效 - 你写的Mock的
get方法没有匹配原生ConfigService.get的重载,没有处理第二个默认值参数,行为和原生实现不符 - 自定义Fake类没有实现
ConfigService的全量接口,导致类型校验报错,没有被正确注入
修复方案
1. 修复现有测试用例
你可以直接移除不需要的ConfigModule导入,同时修正get方法的Mock逻辑,修正后的测试代码如下:
import { Test, TestingModule } from '@nestjs/testing'; import { ConfigService } from '@nestjs/config'; describe('NestJS Configuration .env', () => { let service: ConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ { provide: ConfigService, useValue: { get: jest.fn((key: string, defaultValue?: string) => { if (key === 'FILES') { return './fakedata/'; } else if (key === 'PORT') { return '9999'; } return defaultValue; }), }, }, ], }).compile(); service = module.get<ConfigService>(ConfigService); }); it('should be defined', () => { expect(service).toBeDefined(); }); it.each([ ['FILES=', 'FILES', './', './fakedata/'], ['PORT=', 'PORT', '2000', '9999'], ['default value when key is not found', 'NOTFOUND', './', './'], ])('should get from the .env file, %s', (Text: string, Key: string, Default: string, Expected: string) => { const Result: string = service.get<string>(Key, Default); expect(Key).toBeDefined(); expect(Result).toBe(Expected); }); });
如果你必须保留ConfigModule的导入,可以用overrideProvider方法明确覆盖原有实现:
const module: TestingModule = await Test.createTestingModule({ imports: [ConfigModule.forRoot({ expandVariables: true })], }) .overrideProvider(ConfigService) .useValue({ get: jest.fn((key: string, defaultValue?: string) => { if (key === 'FILES') return './fakedata/'; if (key === 'PORT') return '9999'; return defaultValue; }) }) .compile();
2. 修复可复用Fake类
让Fake类继承原生ConfigService,只重写你需要的get方法即可,既满足类型要求,也不需要实现所有无关方法:
import { ConfigService } from '@nestjs/config'; export class ConfigServiceFake extends ConfigService { override get(key: string, defaultValue?: unknown): unknown { switch (key) { case 'FILES': return './fakedata/'; case 'PORT': return '9999'; default: return defaultValue ?? null; } } }
使用的时候直接通过useClass注入即可:
providers: [ { provide: ConfigService, useClass: ConfigServiceFake } ]
内容的提问来源于stack exchange,提问作者Steven Scott
相关产品推荐
相关产品推荐

