Jest + Nestjs + Nestjsx Crud |无法设置 属性 findOne of [object Object] 只有 getter

Jest + Nestjs + Nestjsx Crud | Cannot set property findOne of [object Object] which has only a getter

我将 Nestjs 与 Nestjsx-Crud 库一起使用。服务 classes 扩展了 TypeOrmCrudService。我需要一些扩展 TypeOrmCrudService 示例的服务。有人有任何 link 或知道如何解决下面的错误吗?

目前是我的代码:

//jobService.spec

beforeAll(async () => {
    jobsModule = await Test.createTestingModule({
      providers: [
        JobsService,
        { provide: getRepositoryToken(Job), useClass: JobsMockRepository },
        // dependencies

        JobTypesService,
        { provide: getRepositoryToken(JobType), useClass: JobTypesMockRepository },
      ],
    }).compile();

    jobsService = jobsModule.get<JobsService>(JobsService);
    jobsRepositoryMock = jobsModule.get(getRepositoryToken(Job));
    jobTypesService = jobsModule.get<JobTypesService>(JobTypesService);
  });

  describe('acceptJob', () => {
    it(`should return ${notFoundMessage('JobType')}`, async () => {
      const job = Mocks.getJob();
      jest.spyOn(jobTypesService, 'findOne').mockImplementation(() => undefined);
      expect(
        await jobsService.acceptJob(job.id, { serviceProviderId: faker.random.uuid() }),
      ).toThrow(notFoundMessage('JobType'));
    });
// mockRepository

export class MockRepository<T> {
  public createQueryBuilder = jest.fn(() => this.queryBuilder);
  public manager = { transaction: (a) => Promise.resolve(a()) };
  public metadata = { connection: { options: { type: null } }, columns: [], relations: [] };
  public save = jest.fn();
  public delete = jest.fn();
  public update = jest.fn();
  public findOne = jest.fn();
  public findOneOrFail = jest.fn();
  public find = jest.fn();
  public getMany = jest.fn();
  public queryBuilder = {
    offset: jest.fn().mockReturnThis(),
    take: jest.fn().mockReturnThis(),
    orderBy: jest.fn().mockReturnThis(),
    skip: jest.fn().mockReturnThis(),
    limit: jest.fn().mockReturnThis(),
    from: jest.fn().mockReturnThis(),
    addFrom: jest.fn().mockReturnThis(),
    where: jest.fn().mockReturnThis(),
    andWhere: jest.fn().mockReturnThis(),
    innerJoinAndSelect: jest.fn().mockReturnThis(),
    leftJoinAndSelect: jest.fn().mockReturnThis(),
    getManyAndCount: jest.fn(),
    getMany: jest.fn(),
    getOne: jest.fn(),
    delete: jest.fn().mockReturnThis(),
    execute: jest.fn().mockReturnThis(),
  };
}

export class JobsMockRepository extends MockRepository<Job> {}
export class JobTypesMockRepository extends MockRepository<JobType> {}
-----------------
 TypeError: Cannot set property findOne of [object Object] which has only a getter
| 
|       77 |     it(`should return ${notFoundMessage('JobType')}`, async () => {
|       78 |       const job = Mocks.getJob();
|     > 79 |       jest.spyOn(jobTypesService, 'findOne').mockImplementation(() => undefined);
|          |            ^
|       80 |       expect(
|       81 |         await jobsService.acceptJob(job.id, { serviceProviderId: faker.random.uuid() }),
|       82 |       ).toThrow(notFoundMessage('JobType'));
| 
|       at ModuleMockerClass.spyOn (../node_modules/jest-mock/build/index.js:800:26)
|       at Object.<anonymous> (modules/jobs/jobs.service.spec.ts:79:9)

有人可以帮我吗?


解决方案:

而不是模拟扩展 TypeOrmCrud 的服务方法,而是模拟存储库 class 方法:

jest.spyOn(jobTypesRepositoryMock, 'findOne').mockResolvedValue(
                () => undefined);

谢谢@michalk93

-------------------------------------------- ---------------------------------------------- ---------------------------------------------- ---------------------------------------------- ---------------------------------------------- ---------------------------------------------- --------------


因为 findOne 方法在 TypeScript 定义中是 readonly 属性,所以不能使用 jest.spyOn 甚至 Object.assign 重新分配。如果你想模拟 findOne 方法,你可以查看 TypeOrmCrudService 的 TypeScript 定义,你会看到那行

readonly findOne: Repository<T>['findOne'];

这意味着您可以模拟服务 findOne 方法而不是存储库 findOne 方法来获得相同的结果。

所以解决方案已经在您的存储库模拟中。您可以像下面这样将 findOne 方法的定义设置为 return undefinedfindOne 就像您现在在测试中所做的那样:

public findOne = jest.fn().mockReturnValue(undefined);