当前位置: 首页 > 面试题库 >

将同一提供程序的两个实例嵌套JS

邹宏峻
2023-03-14
问题内容

嗨,在一个测试套件上,我看来我有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。您将此提供程序及其注入的依赖项作为模拟导入。您不导入模块。

假设我们有一个UsersService取决于的DatabaseConnection

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([]);

在端到端测试中,您要测试整个应用程序,并由此测试您已进行单元测试的部分之间的交互。因此,您不必导入单个提供程序,而是导入一个模块,通常是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();


 类似资料:
  • 我正在使用代码优先和EF6创建一个小项目,但现在我面临一个问题: 如果一个实体有一个自动ID PK,并且例如3个实体(ID:1,ID:2,ID:4-Id3已删除),那么克隆上下文将具有(ID:1,ID:2,ID:3)的实体。 我的问题是:有没有办法强制AI PK的值,或者至少强制跳过ID?或者,是否有通过dbcontexts将数据库复制到另一个数据库的最佳方法? 我在这里发现了一篇关于编程生成ID

  • 我想在Spring引导管理服务器中注册同一个应用程序的两个实例(只有端口不同)。但是我在我的Spring引导管理面板中只看到一个实例(MyApp实例2)。我的配置有什么问题? 基本信息: Spring Boot管理客户端-2.0.0-SNAPSHOT Spring Boot管理服务器-2.0.0-SNAPSHOT Spring Boot版本(两者)-2.0.1。发布 我的申请书。yml文件:

  • 有人能想出一个变通方法来解决osascript索引按名称瓶颈引用同一应用程序的多个实例吗? 如果我们获得两个进程id-一个用于同一个应用程序的两个不同实例,osascript返回相同的实例来交换其中一个pid-就像它首先将pid映射到一个应用程序名称,然后检索具有该名称的第一个应用程序进程一样。 例如,启动两个不同的VLC实例。应用程序,播放两个不同的视频文件,类似: 然后获取两个单独的应用程序进

  • 问题内容: 可以说我有: 我有一个 ApplicationModule ,它需要为 Rec 和 Circle 提供实例: 和 ApplicationComponent : 以这种方式使用代码-无法编译。错误说 错误:(33,20)错误:形状被绑定多次。 对我来说,这是不可行的,因为该组件正试图找到一个实例,并且它找到了两个实例,因此它不知道要返回哪个实例。 我的问题是-我该如何处理? 问题答案:

  • 问题内容: 我正在尝试将Entity Framework与MySQL配合使用,但出现上述错误。我安装了最新的MySQL连接器。 完整错误为: 但是,我找不到任何建议说明您如何在“ entityFramework”部分中进行注册的内容。 其他一些帖子(例如)建议将提供程序添加到该 部分中,如下所示: 但这不起作用,因为它声称名称是重复的。而且,如果我实际上遍历了,我可以看到最后一个是MySQL提供程

  • 问题内容: 当我尝试在同一元素上嵌套两个指令时,出现以下错误。 嵌套的“ E”指令-要求新的/隔离范围的多个指令 ,我想嵌套两个“ E”隔离范围的指令,就像这个小提琴一样。(要真正重现该问题,您需要取消注释 指令) 我不断收到这个我不了解/不知道如何解决的错误: 这不行吗?谢谢! 问题答案: remove replace: 指令名称为’lw’时为 true .. 那也应该解决。 更新小提琴:更新小