在 NestJS Jest 测试中覆盖提供者 [英] Overriding providers in NestJS Jest tests
问题描述
我想使用内存中的 Mongo 实例来模拟数据,以便在我的 NestJS 应用程序中进行测试.我有一个数据库提供程序,它使用 mongoose 连接到我的生产数据库,它是我的数据库模块的一部分,而后者又被导入到其他模块中.
I want to use an in-memory Mongo instance to mock data for testing purposes in my NestJS application. I have a database provider which connects to my production db using mongoose, which is part of my database module, which in turn gets imported into other modules.
我试图在我的 Jest 测试中覆盖数据库提供程序,以便我可以使用内存中的 Mongo 实例.
I am trying to override the database provider within my Jest tests so I can use the in-memory Mongo instance.
这是数据库模块:
import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';
@Module({
providers: [...databaseProviders],
exports: [...databaseProviders],
})
export class DatabaseModule { }
和数据库提供者:
export const databaseProviders = [
{
provide: 'DbConnectionToken',
useFactory: async (): Promise<typeof mongoose> =>
await mongoose.connect(PRODUCTION_DATABASE_URL),
},
];
我有一个事件模块,它从数据库模块导入和使用数据库连接,事件服务是我正在测试的 - 我的 events.spec.ts 中的 beforeEach:
I have an Events module which imports and uses the database connection from the database module the Events service is what I am testing - the beforeEach in my events.spec.ts:
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [EventsModule],
providers: [
EventsService,
{
provide: 'EventModelToken',
useValue: EventSchema
},
],
}).compile();
eventService = module.get<EventsService>(EventsService);
});
我尝试将 DatabaseModule 导入测试模块,然后添加我的自定义提供程序,假设它会覆盖数据库提供程序,但它没有按我预期的那样工作,所以我担心我可能会误解覆盖提供程序在这种情况下的工作方式.
I tried importing the DatabaseModule into the testing module and then adding my custom provider assuming it would override the database provider, but it doesn't work as I expected so I fear I may misunderstand how overriding providers works in this context.
这是我试过的:
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [EventsModule, DatabaseModule],
providers: [
EventsService,
{
provide: 'EventModelToken',
useValue: EventSchema
},
{
provide: 'DbConnectionToken',
useFactory: async (): Promise<typeof mongoose> =>
await mongoose.connect(IN_MEMORY_DB_URI),
},
],
}).compile();
eventService = module.get<EventsService>(EventsService);
});
推荐答案
如文档中所述 https://docs.nestjs.com/fundamentals/unit-testing 您可以使用值、工厂或类覆盖提供程序.
As specified in the docs https://docs.nestjs.com/fundamentals/unit-testing you can override the provider with a value, factory or class.
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [EventsModule, DatabaseModule],
providers: [
EventsService,
],
}).overrideProvider('DbConnectionToken')
.useFactory({
factory: async (): Promise<typeof mongoose> =>
await mongoose.connect(IN_MEMORY_DB_URI),
})
.compile();
eventService = module.get<EventsService>(EventsService);
});
另一种方法是为您的配置创建一个提供程序 :) 像这样!
An alternative would be to make a provider for your configs :) Like so!
@Module({})
export DatabaseModule {
public static forRoot(options: DatabaseOptions): DynamicModule {
return {
providers: [
{
provide: 'DB_OPTIONS',
useValue: options,
},
{
provide: 'DbConnectionToken',
useFactory: async (options): Promise<typeof mongoose> => await mongoose.connect(options),
inject: ['DB_OPTIONS']
},
],
};
}
}
然后像这样使用
const module: TestingModule = await Test.createTestingModule({
imports: [DatabaseModule.forRoot({ host: 'whatever'})],
});
现在您可以随时随地更改选项:)
Now you're able to change the options wherever you're using it :)
这篇关于在 NestJS Jest 测试中覆盖提供者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!