nestjs 单元测试 createTestingModule 依赖注入
Posted
技术标签:
【中文标题】nestjs 单元测试 createTestingModule 依赖注入【英文标题】:nestjs unit test createTestingModule Dependency Injection 【发布时间】:2021-05-29 06:01:46 【问题描述】:我希望你能帮助我。 我正在使用带有最新 angular/nestjs 的 Nx(日期:2 月 26 日)
...
"@nestjs/common": "^7.0.0",
"@nestjs/config": "^0.6.3",
"@nestjs/core": "^7.0.0",
"@nestjs/platform-express": "^7.0.0",
"@nestjs/platform-socket.io": "^7.6.7",
"@nestjs/websockets": "^7.6.7",
"jest": "26.2.2",
"@nrwl/jest": "11.4.0",
...
我无法使用带有 Jest 的 NestJS 运行我的单元测试 我想测试以下服务:
@Injectable()
export class CoreApiService
logger = new Logger('CoreApiService');
apiEndpoint;
constructor(private httpService: HttpService, configService: ConfigService)
this.apiEndpoint = configService.get('API_SERVICE_ENDPOINT');
我收到以下错误:
TypeError: Cannot read property 'get' of undefined
所以看来 ConfigService(以及 httpService)总是未定义的。
当记录 httpService 和 ConfigService 时,它总是未定义的。
即使我尝试实例化像new CoreApiService(new HttpService(), new ConfigService())
这样的新实例
我什至在测试本身中尝试过 new CoreApiService( as any, get: (...params => return 'foo')
之类的东西
总是会出现上述相同的错误。
测试文件:
import Test, TestingModule from '@nestjs/testing';
import CoreApiService from './core-api.service';
import ConfigModule, ConfigService from '@nestjs/config';
import HttpModule from '@nestjs/common';
class ConfigServiceMock
get(key: string): string
switch (key)
case 'API_SERVICE_ENDPOINT':
return '';
describe('CoreApiService', () =>
let module: TestingModule;
let service: CoreApiService;
beforeEach(async () =>
module = await Test.createTestingModule(
imports: [HttpModule, ConfigModule],
providers: [
CoreApiService,
provide: ConfigService, useClass: ConfigServiceMock ,
],
).compile();
service = module.get<CoreApiService>(CoreApiService);
);
it('should be defined', () =>
expect(service).toBeDefined();
);
);
我什至试过:.overrideProvider(ConfigService).useClass(ConfigServiceMock)
提前谢谢你!
编辑 03/01
似乎模块本身的编译步骤失败了... 所以对于当前的测试文件,日志“COMPILED”将永远不会被执行。
CoreApiService › should be defined
TypeError: Cannot read property 'get' of undefined
22 |
23 | constructor(private httpService: HttpService, configService: ConfigService)
> 24 | this.apiEndpoint = configService.get('API_SERVICE_ENDPOINT');
| ^
25 |
26 |
27 | private static createRequestConfig(options: RequestHeader): RequestConfig
at new CoreApiService (src/app/core-api/core-api.service.ts:24:38)
at Injector.instantiateClass (../../node_modules/@nestjs/core/injector/injector.js:286:19)
at callback (../../node_modules/@nestjs/core/injector/injector.js:42:41)
at Injector.resolveConstructorParams (../../node_modules/@nestjs/core/injector/injector.js:114:24)
at Injector.loadInstance (../../node_modules/@nestjs/core/injector/injector.js:46:9)
at Injector.loadProvider (../../node_modules/@nestjs/core/injector/injector.js:68:9)
at async Promise.all (index 5)
at InstanceLoader.createInstancesOfProviders (../../node_modules/@nestjs/core/injector/instance-loader.js:43:9)
at ../../node_modules/@nestjs/core/injector/instance-loader.js:28:13
at async Promise.all (index 1)
at InstanceLoader.createInstances (../../node_modules/@nestjs/core/injector/instance-loader.js:27:9)
at InstanceLoader.createInstancesOfDependencies (../../node_modules/@nestjs/core/injector/instance-loader.js:17:9)
at TestingModuleBuilder.compile (../../node_modules/@nestjs/testing/testing-module.builder.js:43:9)
● CoreApiService › should be defined
expect(received).toBeDefined()
Received: undefined
44 | it('should be defined', () =>
45 | console.log('SHOULD BE DEFINED')
> 46 | expect(service).toBeDefined();
| ^
47 | );
48 | );
49 |
at Object.<anonymous> (src/app/core-api/core-api.service.spec.ts:46:21)
当前测试文件如下:
import Test, TestingModule from '@nestjs/testing';
import CoreApiService from './core-api.service';
import ConfigService from '@nestjs/config';
import HttpService, INestApplication from '@nestjs/common';
class ConfigServiceMock
get(key: string): string
switch (key)
case 'API_SERVICE_ENDPOINT':
return '';
class HttpServiceMock
get(): any
describe('CoreApiService', () =>
let module: TestingModule;
let service: CoreApiService;
let app: INestApplication;
beforeEach(async () =>
console.log('beforeEach')
module = await Test.createTestingModule(
imports: [],
providers: [
provide: ConfigService, useClass: ConfigServiceMock ,
provide: HttpService, useClass: HttpServiceMock ,
CoreApiService,
],
)
.compile();
console.log('COMPILED');
app = module.createNestApplication();
await app.init();
service = module.get<CoreApiService>(CoreApiService);
);
it('should be defined', () =>
console.log('SHOULD BE DEFINED')
expect(service).toBeDefined();
);
);
我也玩过提供者部分的顺序,但我想这无关紧要......
【问题讨论】:
删除ConfigModule
,但通常您的模拟和测试设置看起来不错。我也会嘲笑HttpService
,但它应该可以工作
您可以使用useValue
而不是useClass
代替ConfigServiceMock
,然后使用地图。这样你就不需要模拟 get
函数。 (例如:const ConfigServiceMock = new Map([['foo', 'bar']]);
)
【参考方案1】:
您可能想尝试的两件事:
-
初始化您的 Nest 应用程序。在
beforeEach
中,在您的模块中调用compile()
之后,添加以下行:
app = module.createNestApplication();
await app.init();
-
不要在您的测试中导入
ConfigModule
。这将初始化实际的配置服务,你在模拟它时不需要它。
【讨论】:
感谢您的建议。我已经尝试删除 ConfigModule 并完成了这个测试,但没有成功 即使使用创建嵌套应用程序和编译后的等待,测试也会因以下错误而中断:```TypeError: Cannot read property 'get' of undefined 所以配置服务仍然未定义跨度>以上是关于nestjs 单元测试 createTestingModule 依赖注入的主要内容,如果未能解决你的问题,请参考以下文章
在 NestJS 中使用 Jest 和 MongoDB 进行单元测试