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 undefined
从 findOne
就像您现在在测试中所做的那样:
public findOne = jest.fn().mockReturnValue(undefined);
我将 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 undefined
从 findOne
就像您现在在测试中所做的那样:
public findOne = jest.fn().mockReturnValue(undefined);