Гнездо JS два экземпляра одного и того же провайдера - PullRequest
1 голос
/ 15 марта 2019

Привет, в тестовом наборе мне кажется, что у меня есть 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% уверен, что оба метода были вызваны на тестируемом сервисе, но второй по какой-то причине не был заменен фиктивным

1 Ответ

3 голосов
/ 15 марта 2019

Вы смешиваете концепции модульных тестов и сквозных (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([]);

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

Как создавать макеты?

См. этот ответ .

...