微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – Nest JS同一个提供者的两个实例

嗨,在测试套件上,在我看来,我有2个相同提供者的生活实例,一个用于实现,另一个用于实际实现.

我的结论基于一个事实,在我的测试中,我尝试通过jest.fn调用替换方法但仍然,在我测试的服务上,该方法仍然指向原始实现.

更奇怪的是,我能够模拟另一个服务执行完全相同的过程,就好像,根据这些服务的注入方式(它们来自容器图中的位置)它是否有效.

我会尝试分享一些片段,但当然,只有一个小的回购实际上可以重现它,但也许有人有洞察力:

 beforeAll(async done => {
    app = await Test.createTestingModule({
      imports: [
        SOME_MODULES,
      ],
      providers: [
        Essayapplicationservice,
        ReviewFacade,
        ExamCacheResultService,
      ],
    }).compile();

    essayapplicationservice = app.get<Essayapplicationservice>(Essayapplicationservice)
    reviewFacade = app.get<ReviewFacade>(ReviewFacade)
    examCacheResult = app.get<ExamCacheResultService>(ExamCacheResultService)
    await app.init()
    done()
  })
it('should invoke review only once', async done => {

    reviewFacade.startReview = jest.fn() --> this works
    examCacheResult.clearCachedResult = jest.fn() --> this fails

    await essayapplicationservice.finishApplication()

    expect(reviewFacade.startReview).toHaveBeenCalledTimes(1)
    expect(reviewFacade.startReview).toHaveBeenCalledWith(expect.objectContaining({ id: 1 }))
    expect(examCacheResult.clearCachedResult).toHaveBeenCalledTimes(1) ---> here this fails, although it's called!!

所以,问题归结为这样一个事实:我100%肯定这两种方法都被测试的服务调用,但第二种由于某种原因没有被模拟所取代

解决方法:

您正在混合单元测试和端到端(e2e)测试的概念.您正在导入模块,同时直接导入单个提供程序.我假设你导入的一个模块也导入了ExamCacheResultService.这样,您的测试应用程序中就有两个.当您调用app.get(ExamCacheResultService)时,您将获得在测试模块中直接声明的实例.但是调用finishApplication时使用的那个是另一个.确定要测试的内容并遵循以下原则:

单元测试

在单元测试中,您希望测试与其他依赖关系隔离的单个提供者/控制器,例如UserService或UsersController.您将此提供程序及其注入的依赖项导入为mocks.您不导入模块.

假设我们有一个依赖于DatabaseConnection的UseRSService:

export class UseRSService {
  constructor(private connection: DatabaseConnection) {}
  // ...
}

在单元测试中,导入UseRSService,模拟DatabaseConnection但不导入UsersModule.

module = await Test.createTestingModule({
  providers: [
    UseRSService,
    { provide: DatabaseConnection, useClass: DbConnectionMock },
  ],
}).compile();
databaseMock = module.get(DatabaseConnection);
databaseMock.findMany.mockReturnValue([]);

E2E测试

在端到端测试中,您希望测试整个应用程序,并预测您事先进行单元测试的部件之间的交互.因此,您不要导入单个提供程序,而是导入模块,通常是AppModule.然后,您可以覆盖单个提供商,例如如果要在内存数据库而不是实际数据库上进行测试,或者想要模拟外部API的结果.

const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    }).overrideProvider(DatabaseConnection).useClass(InMemoryDatabaseConnection)
      .overrideProvider(ExternalApiService).useValue(externalApiMock)
      .compile();
    app = moduleFixture.createnestApplication();
    externalApiMock.get.mockReturnValueOnce({data: [...]});
    await app.init();

如何创建模拟?

this answer.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐