gpt4 book ai didi

javascript - 嵌套 JS 同一个提供者的两个实例

转载 作者:行者123 更新时间:2023-12-01 15:52:49 26 4
gpt4 key购买 nike

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

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

更奇怪的是,我能够模拟另一个执行完全相同过程的服务,就好像取决于这些服务的注入(inject)方式(它们来自容器图中的位置)它会起作用或不起作用。

我会尝试分享一些片段,但当然,只有一个小的 repo 可以真正重现它,但也许有人有洞察力:

 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 时使用的那个是另一个。确定您要测试的内容并遵循以下原则:

单元测试

在单元测试中,您想测试与其他依赖项隔离的单个提供程序/ Controller ,例如UserServiceUsersController .您将此提供程序及其注入(inject)的依赖项作为模拟导入。您不导入模块。

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

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

在您的单元测试中,您导入 UsersService ,你 mock 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();

如何创建模拟?

this answer .

关于javascript - 嵌套 JS 同一个提供者的两个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55175262/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com