NestJS + Mongoose:如何测试 document(data).save()?

Posted

技术标签:

【中文标题】NestJS + Mongoose:如何测试 document(data).save()?【英文标题】:NestJS + Mongoose: How to test for document(data).save()? 【发布时间】:2021-01-31 23:04:18 【问题描述】:

由于我使用了一些抽象,这里的代码只接收一个用户,将其更改为 Mongo 格式(也就是在其他地方生成的 id 中添加一个下斜线),保存然后返回保存的用户,id 上没有下斜线:

  constructor(
    @InjectModel('User')
    private readonly service: typeof Model
  )  

  async saveUser(user: User): Promise<User> 
    const mongoUser = this.getMongoUser(user);
    const savedMongoUser = await new this.service(mongoUser).save();
    return this.toUserFormat(savedMongoUser);
  

我正在尝试的测试:

  beforeEach(async () => 
        const module: TestingModule = await Test.createTestingModule(
          providers: [
            MongoUserRepository,
            
              provide: getModelToken('User'),
              useValue:  ... , // all used functions with jest.fn()
            ,
          ],
        ).compile();
    service = module.get<MongoUserRepository>(MongoUserRepository);
    model = module.get<Model<UserDocument>>(getModelToken('User'));
  );

  it('should save new user', async () => 
    jest.spyOn(model, 'save').mockReturnValue(
      save: jest.fn().mockResolvedValueOnce(mockMongoFormat)
     as any);

    const foundMock = await service.saveUser(mockUserFormat);
    expect(foundMock).toEqual(mockUserFormat);
  );

问题:

No overload matches this call.
  Overload 1 of 4, '(object: Model<UserDocument, >, method: "model" | "remove" | "deleteOne" | "init" | "populate" | "replaceOne" | "update" | "updateOne" | "addListener" | "on" | ... 45 more ... | "where"): SpyInstance<...>', gave the following error.
    Argument of type '"save"' is not assignable to parameter of type '"model" | "remove" | "deleteOne" | "init" | "populate" | "replaceOne" | "update" | "updateOne" | "addListener" | "on" | "once" | "removeListener" | "off" | "removeAllListeners" | ... 41 more ... | "where"'.
  Overload 2 of 4, '(object: Model<UserDocument, >, method: "collection"): SpyInstance<Collection, [name: string, conn: Connection, opts?: any]>', gave the following error.
    Argument of type '"save"' is not assignable to parameter of type '"collection"'.ts(2769)

尝试使用“新”也是不行的:

No overload matches this call.
  Overload 1 of 4, '(object: Model<UserDocument, >, method: "find" | "watch" | "translateAliases" | "bulkWrite" | "model" | "$where" | "aggregate" | "count" | "countDocuments" | ... 46 more ... | "eventNames"): SpyInstance<...>', gave the following error.
    Argument of type '"new"' is not assignable to parameter of type '"find" | "watch" | "translateAliases" | "bulkWrite" | "model" | "$where" | "aggregate" | "count" | "countDocuments" | "estimatedDocumentCount" | "create" | "createCollection" | ... 43 more ... | "eventNames"'.
  Overload 2 of 4, '(object: Model<UserDocument, >, method: "collection"): SpyInstance<Collection, [name: string, conn: Connection, opts?: any]>', gave the following error.
    Argument of type '"new"' is not assignable to parameter of type '"collection"'.

我可能会更改实现...但真的很想知道在这种情况下该怎么做...我应该如何模拟该功能?

【问题讨论】:

您是如何在测试中注入模型/服务的(可能是通过beforeAll)? @GytisTG 是的,这实际上是我需要通过的最后一个测试。甚至 'findOneAndUpdate' 和 'findOneAndDelete' 也有效。 【参考方案1】:

放弃了一段时间后,回来做了这个:

async saveUser ( user: User ): Promise<User> 
    const mongoUser = this.getMongoUser(user);
    const savedMongoUser = await this.service.create( mongoUser );
    return this.toUserFormat(savedMongoUser);

从 new service(doc).save() 更改为 service.create(doc)

通过测试变成:

  it( 'should save new user', async () => 
    jest.spyOn( model, 'create' ).mockImplementation(
      jest.fn().mockResolvedValueOnce( mockMongoFormat )
    );
    const foundMock = await service.saveUser( mockUserFormat );
    expect( foundMock ).toEqual( mockUserFormat );
   );

有了这个... 100% 的覆盖率。好的。

【讨论】:

以上是关于NestJS + Mongoose:如何测试 document(data).save()?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Jest 和 NestJS 模拟 Mongoose 的“lean()”查询?

NestJS - 如何自我引用 mongoDB 架构 @nestjs/mongoose?

TypeError:在使用 Jests 和 Mongoose 测试 NestJS API 时,updatedService.save 不是一个函数

如何在 NestJs 和 typescript 中使用 `mongoose-delete` 插件?

在 @nestjs/mongoose 中设置 mongoose 全局选项

使用@nestjs/mongoose 时如何在文档界面中定义静态猫鼬方法?