【问题标题】:nestjs mock imported modulenestjs 模拟导入模块
【发布时间】:2020-06-30 13:20:16
【问题描述】:

我正在尝试使用supertest 测试我的AuthModule 控制器HTTP 层,如官方Nestjs documentation 中所述。此模块使用从 EmailModule 导入的 EmailService

我知道您可以按如下方式覆盖提供程序:

const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [
        AuthModule,
      ],
    })
      .overrideProvider(EmailService)
      .useValue(buildMock(EmailService))

但这不起作用,我假设是因为EmailModule 是在AuthModule 中导入的。一种解决方法是.overrideProvider(...).useValue(...)EmailModule 中的每个提供程序,但这毫无意义,因为我还必须模拟由EmailModule 导入的模块。

当我对AuthModule 进行e2e 测试时,老实说,我并不关心EmailModule 的工作原理。我只需要模拟EmailService 并确保我的身份验证模块与该服务正确交互。

很遗憾,Test.createTestingModule({}) 没有 .overrideModule() 方法。

我试着用玩笑来嘲笑EmailModule

jest.mock('../../src/email/email.module.ts', () => {
  @Module({})
  class EmailModule {

  }

  return EmailModule;
});

但我收到此错误:

Error: Nest cannot create the module instance. Often, this is because of a circular dependency between modules. Use forwardRef() to avoid it.

(Read more: https://docs.nestjs.com/fundamentals/circular-dependency)
Scope [RootTestModule -> AppModule]

有谁知道如何做到这一点?

【问题讨论】:

  • "我假设是因为 EmailModule 是在 AuthModule 中导入的" 不,overrideProvider 允许覆盖上下文中的任何提供程序。因此,如果EmailService 存在于您的应用程序上下文中,它将被覆盖。您能显示AuthModuleEmailModule@Module() 部分吗?
  • 是的,覆盖 EmailService 不是问题。我遇到的问题是我想模拟整个电子邮件模块,而不必模拟导入的所有内容以及该模块的每个提供者。我的 EmailModule 导出一个 EmailService 并使用一个 EmailRepository,所以在这种情况下我必须模拟两者。我想要的是告诉 AuthModule 使用假的 EmailModule,我可以手动提供 EmailService。
  • 嗨!你解决了这个问题吗?我在这里面临同样的问题,但我还没有找到解决方案。
  • 不,直到今天我还没有找到解决方案,对不起:(
  • 我也需要一个解决方案,因此在nestjs中测试很痛苦

标签: testing jestjs nestjs


【解决方案1】:

您是否尝试仅在测试模块中提供 EmailService?它看起来像这样:

const module: TestingModule = await Test.createTestingModule({
  controllers: [AuthController],
  providers: [
    EmailService        
  ],
}).compile();

我认为您可以跳过导入整个 EmailModule 并提供所需的内容

【讨论】:

    【解决方案2】:

    我解决这个问题的方法是创建一个全局的TestModule

        @Global()
        @Module({
          providers: [
            {
              provide: EmailService,
              useValue: {} // mock
            },
          ],
        })
        class TestModule {}
    

    在测试模块的开头导入TestModule

        const module = await Test.createTestingModule({
          imports: [
            TestModule,
            AuthModule,
            // ...
          ]
        }).compile();
    

    这样,EmailService 是全局提供的,您无需再导入 EmailModule

    全局模块解释here

    【讨论】:

      【解决方案3】:

      我花了很长时间试图弄清楚如何模拟一个完整的 NestJS 模块。以下是适合我的方法。

      // Create a valid NestJS module to be used in place of the one we want to mock
      @Module({})
      class MockModule {}
      
      // Identify the Module you want to mock and mock it
      jest.mock('module-to-mock', () => {
        return {
          ModuleToMockName: {
            forRootAsync: jest.fn().mockImplementation(() => MockModule),
          }
        };
      });
      

      基本上,我们为 NestJS 提供了一个有效的模块,在这种情况下,它什么都不做,但可以被编码为以可预测/可测试的方式运行。

      【讨论】:

        猜你喜欢
        • 2021-11-06
        • 2021-09-18
        • 2020-05-27
        • 1970-01-01
        • 2011-11-09
        • 2022-11-14
        • 2023-01-31
        • 2020-02-02
        • 2020-12-21
        相关资源
        最近更新 更多