Lui*_*Rol 1 javascript node.js typescript jestjs nestjs
嗨,在一个测试套件上,我看来我有两个同一提供者的活动实例,一个实例用于实现,另一个实例用于实际实现。
我的结论基于这样一个事实:在测试中,我尝试用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()
})
Run Code Online (Sandbox Code Playgroud)
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!!
Run Code Online (Sandbox Code Playgroud)
因此,问题归结为以下事实:对于测试中的服务调用了这两种方法,我100%表示肯定,但是由于某种原因第二种方法并未被模拟代替
您正在混合单元测试和端到端(e2e)测试的概念。您正在导入模块,同时直接导入单个提供程序。我假设您导入的模块之一也可以导入ExamCacheResultService。这样,您的测试应用程序中就有两个。调用时app.get(ExamCacheResultService),您将获得在测试模块中直接声明的实例。但是呼叫时使用的finishApplication是另一个。确定要测试的内容并遵循以下原则:
在单元测试中,您要测试与其他依赖项(例如UserService或)隔离的单个提供者/控制器UsersController。您将此提供程序及其注入的依赖项作为模拟导入。您不导入模块。
假设我们有一个UsersService取决于的DatabaseConnection:
export class UsersService {
constructor(private connection: DatabaseConnection) {}
// ...
}
Run Code Online (Sandbox Code Playgroud)
在单元测试中,您导入UsersService,模拟,DatabaseConnection但不导入UsersModule。
module = await Test.createTestingModule({
providers: [
UsersService,
{ provide: DatabaseConnection, useClass: DbConnectionMock },
],
}).compile();
databaseMock = module.get(DatabaseConnection);
databaseMock.findMany.mockReturnValue([]);
Run Code Online (Sandbox Code Playgroud)
在端到端测试中,您要测试整个应用程序,并由此测试您已进行单元测试的部分之间的交互。因此,您不必导入单个提供程序,而是导入一个模块,通常是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();
Run Code Online (Sandbox Code Playgroud)
看到这个答案。
| 归档时间: |
|
| 查看次数: |
609 次 |
| 最近记录: |