node.js - NestJS 模拟从不同模块导入的注入(inject)连接

标签 node.js typescript mongodb mongoose nestjs

我一整天都收到这个错误:

Nest can't resolve dependencies of the ClubsService (ClubsApiService, AuthApiService, ClubFollowersRepo, ClubsRepo, ClubPrivacyRepo, ?). Please make sure that the argument DatabaseConnection at index [5] is available in the ClubsModule context.

Potential solutions:
- If DatabaseConnection is a provider, is it part of the current ClubsModule?
- If DatabaseConnection is exported from a separate @Module, is that module imported within ClubsModule?
  @Module({
    imports: [ /* the Module containing DatabaseConnection */ ]
  })

我认为问题在于我没有模拟 Mongo DB 连接。错误很明显,ClubsService 中的@InjectConnection 应该被模拟(见下文)。

俱乐部服务:

@Injectable()
export class ClubsService {
  constructor(
    private readonly clubsApiService: ClubsApiService,
    private readonly authApiService: AuthApiService,
    private readonly clubFollowersRepo: ClubFollowersRepo,
    private readonly clubsRepo: ClubsRepo,
    private readonly clubPrivacyRepo: ClubPrivacyRepo,
    @InjectConnection() private readonly connection: Connection,   // <--- THIS GUY
  ) {}
// ...
}

问题是我正在执行的测试文件与 ClubsService 所在的模块不同。所以在不同的模块中(我们称之为 YModule),我有这段代码:

Y模块:

import { getConnectionToken } from '@nestjs/mongoose';
import { MongoMemoryServer } from 'mongodb-memory-server';
import { Connection, connect } from 'mongoose';

describe('YService.spec.ts in YModule', () => {

  beforeAll(async () => {
    mongod = await MongoMemoryServer.create();
    const uri = mongod.getUri();
    mongoConnection = (await connect(uri)).connection;
  });

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
         // ...
      ],
      imports: [ClubsModule],  // <--- ClubsModule is not provider, but imported module
    })
      .overrideProvider(getConnectionToken())
      .useValue(mongoConnection)
      .compile();
  });
});

这种使用 getConnectionToken() 的方法将不起作用,因为我必须模拟来自导入的 ClubsModule 而不是提供者的连接。

您将如何模拟注入(inject)到您导入的不同模块中的连接?

非常感谢! :)

最佳答案

正如 Jay McDoniel 在帖子评论中提到的,您不应该在单元测试文件中导入模块,而是模拟所需的依赖项。这是为什么?考虑上述问题中的示例:

ClubsModule具有可以用内存数据库服务器替换的连接依赖性,这是真的,但这应该在 ClubsModule 内完成本身(clubs 文件夹),不在不同模块之外。

你真正想在外面做什么ClubsModule ,比方说,在 YModule (y 文件夹),用于模拟每个提供者 ClubsModule您在 YModule 的测试文件中使用的导出.

这是有道理的,因为您应该测试 ClubsModule仅在其模块内的特定依赖项,其他任何地方都只是模拟它。

我原装进口ClubsModule因为我想使用 ClubsModule 的存储库(提供者)导出。但后来我意识到我不想测试存储库函数的功能,我已经在 ClubsModule 中测试了它们,因此无需执行两次。相反,模拟存储库是个好主意。

代码示例:

y.service.spec.ts :

import { YService } from './y.service';  // <--- For illustration; Provider within YModule
import { ClubsRepo } from '../clubs/clubs.repo'; // <--- Import the real Repository Provider from different Module (ClubsModule)

describe('y.service.spec.ts in YModule', () => {

  const clubsRepo = {       // <--- Mocking ClubRepo's functions used within this test file
    insertMany: () => Promise.resolve([]),
    deleteMany: () => Promise.resolve(),
  }
  
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        ClubsRepo,   // <--- The real Repository Provider from the import statement above
      ],
    })
      .overrideProvider(ClubsRepo)  // <--- Overriding the Repository Provider from imports
      .useValue(clubsRepo)  // <--- Overriding to the mock 'clubsRepo' (const above)
      .compile();

    service = module.get<YService>(YService); // <--- For illustration; unlike ClubsRepo, this provider resides within this module 
  });

  it('example', () => {
    // ...
    jest.spyOn(clubsRepo, 'insertMany');  // <--- Using "insertMany" from the mocked clubsRepo (the const) defined at the beginning
    // ...
  });

});

导入原因ClubsRepo到测试文件 y.service.spec.ts是因为y.service.ts (YModule 中的实际 Provider)使用 ClubsRepo 的功能.在这种情况下,不要忘记导入 ClubsModuley.module.ts也是。

y.module.ts :

import { ClubsModule } from '../clubs/clubs.module';

@Module({
  imports: [
    // ...
    ClubsModule,   // <--- Don't forget this line
    // ...
  ],
  providers: [
    // ...
  ],
})
export class YModule {}

就是这样,测试愉快! :)

关于node.js - NestJS 模拟从不同模块导入的注入(inject)连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73709756/

相关文章:

node.js - Windows Azure Node JS WEBSOCKET 握手失败 503 错误

javascript - 使用 mocha/chai 测试几个函数回调

c# - 是 mongodb atomic 中的 upsert 过滤器和实际更新

java - 无法解析 Java 中的 newDate()

javascript - Sequelize 查询获取开始和结束日期之间的所有数据

mongodb - Mongo_mapper 限制结果

javascript - 尝试/捕获不捕获快速异步功能中的所有错误?

node.js - 无法从表单发布数据到nodeJS服务器

javascript - 如何对数组中的每个文件发出 POST 请求

javascript - 创建一个接口(interface),其键是枚举的值