【问题标题】:Overriding providers in NestJS Jest tests在 NestJS Jest 测试中覆盖提供程序
【发布时间】:2019-02-05 07:03:59
【问题描述】:

我想在我的 NestJS 应用程序中使用内存中的 Mongo 实例来模拟数据以进行测试。我有一个数据库提供程序,它使用 mongoose 连接到我的生产数据库,它是我的数据库模块的一部分,然后又被导入到其他模块中。

我试图在我的 Jest 测试中覆盖数据库提供程序,以便可以使用内存中的 Mongo 实例。

这是数据库模块:

import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

@Module({
  providers: [...databaseProviders],
  exports: [...databaseProviders],
})
export class DatabaseModule { }

和databaseProvider:

export const databaseProviders = [
  {
    provide: 'DbConnectionToken',
    useFactory: async (): Promise<typeof mongoose> =>
      await mongoose.connect(PRODUCTION_DATABASE_URL),
  },
];

我有一个事件模块,它从数据库模块导入和使用数据库连接,我正在测试事件服务 - 我的 events.spec.ts 中的 beforeEach:

beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [EventsModule],
      providers: [
        EventsService,
        {
          provide: 'EventModelToken',
          useValue: EventSchema
        },
      ],
    }).compile();

    eventService = module.get<EventsService>(EventsService);
  });

我尝试将 DatabaseModule 导入测试模块,然后添加我的自定义提供程序,假设它会覆盖数据库提供程序,但它没有按我预期的那样工作,所以我担心我可能会误解覆盖提供程序在这种情况下的工作方式。

这是我尝试过的:

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);
});

【问题讨论】:

    标签: jestjs nestjs


    【解决方案1】:

    如文档 https://docs.nestjs.com/fundamentals/unit-testing 中所述,您可以使用值、工厂或类覆盖提供程序。

    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);
    });
    

    另一种方法是为您的配置创建一个提供程序 :) 就像这样!

    @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'})],
    });
    

    现在您可以在任何地方使用它来更改选项 :)

    【讨论】:

    • 我之前尝试过使用 overrideProvider 功能,但我显然没有正确使用它。现在完美运行,感谢您的帮助!
    猜你喜欢
    • 2019-04-08
    • 1970-01-01
    • 2022-01-06
    • 2020-06-03
    • 2019-03-26
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多