typescript - NestJS + Mongoose: چگونه برای document(data).save() تست کنیم؟


از آنجایی که من از برخی انتزاعها استفاده میکنم، کد اینجا فقط یک کاربر دریافت میکند، آن را به فرمت Mongo تغییر میدهد (یعنی به شناسه ایجاد شده در جای دیگر یک زیرخط اضافه میکند)، ذخیره میکند و سپس کاربر ذخیره شده را بدون زیرخط در شناسه برمیگرداند:

  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)

تلاش برای استفاده از «new» نیز امکانپذیر نیست:

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"'.

من احتمالا میتوانم پیادهسازی را تغییر دهم... اما واقعاً دوست دارم بفهمم در این شرایط باید چه کاری انجام دهم... چگونه باید آن تابع را شبیهسازی کنم؟

پاسخ شماره ۱

بعد از اینکه مدتی دست کشید، برگشت و این کار را انجام داد:

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

با این... پوشش ۱۰۰٪. عالی.