NestJS测试报错:Repository未注入,无法读取其属性
NestJS单元测试中ProfilesService的Repository注入失败问题
在对AdsService进行单元测试时,出现报错提示无法读取Repository的属性,报错触发点在ProfilesService的findByProfileId方法调用profileRepository.findOne时,推测是测试环境下Repository未成功注入。
相关业务代码
ads.module.ts
@Module({ imports: [ TypeOrmModule.forFeature([Ads]), ProfilesModule, ], providers: [AdsService], controllers: [AdsController], exports: [AdsService], }) export class AdsModule {}
profile.module.ts
@Module({ imports: [ TypeOrmModule.forFeature([Profiles]), ], providers: [ProfilesService], controllers: [ProfilesController], exports: [ProfilesService], }) export class ProfilesModule {}
ads.service.ts
@Injectable() export class AdsService { constructor( @InjectRepository(Ads) private adsRepository: Repository<Ads>, private profileService: ProfilesService, ) {} create = async (createAdsDto: AdsDto) => { const profile = await this.profileService.findByProfileId( createAdsDto.profileId, ); return null; } }
profiles.service.ts
@Injectable() export class ProfilesService { constructor( @InjectRepository(Profiles) private profileRepository: Repository<Profiles> ) {} findByProfileId = async (id: number): Promise<Profiles> => { // 以下代码触发报错 const profile = await this.profileRepository.findOne({ where: { id }, relations: { user: true, avatar: true }, }); return profile; }; }
测试代码
ads.service.spec.ts
describe('AdsService', () => { let service: AdsService; let adsRepository: Repository<Ads>; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ AdsService, { provide: getRepositoryToken(Ads), useValue: { // 可根据测试需求添加AdsRepository需mock的方法 } }, // 模拟ProfilesService,隔离依赖 { provide: ProfilesService, useValue: { findByProfileId: jest.fn().mockResolvedValue({ id: 1, user: {}, avatar: {} }) } } ], }).compile(); service = module.get(AdsService); adsRepository = module.get<Repository<Ads>>(getRepositoryToken(Ads)); }); afterAll(() => { jest.resetAllMocks(); }); describe('Initial variables must be defined', () => { test('Ads Service must be defined', () => { expect(service).toBeDefined(); }); test('Ads Repository must be defined', () => { expect(adsRepository).toBeDefined(); }); test('can create ads', async () => { const ads = await service.create({ profileId: 1, type: 'Oferta', category: 'Vivienda', location: 'Alicante', title: 'Apartment For Rent', description: 'This is a sample description', extract: 'This is a sample extract short description', } as AdsDto); expect(ads).toBeNull(); // 验证ProfilesService的方法调用情况 const profileService = module.get(ProfilesService); expect(profileService.findByProfileId).toHaveBeenCalledWith(1); }); }); });
报错截图

问题原因及解决方案
问题原因
直接使用useClass: Repository创建Repository实例时,TypeORM的Repository依赖EntityManager等内部资源,测试环境下未初始化这些资源,导致实例内部属性为undefined,调用findOne时触发报错。
解决方案
针对AdsService的单元测试,核心是验证AdsService的逻辑,因此应隔离依赖,直接模拟ProfilesService的方法,而非引入真实的ProfilesService及其依赖的Repository:
- 在测试模块的providers中,用
useValue模拟ProfilesService,预先定义findByProfileId的返回值; - 无需手动注入ProfilesRepository,因为已mock了ProfilesService的行为;
- 若需验证依赖方法的调用情况,可在测试中获取mock的ProfilesService,验证方法调用次数和参数。
如果需要单独测试ProfilesService,才需正确模拟其依赖的Repository,此时可用useValue提供包含mock方法的对象,例如:
{ provide: getRepositoryToken(Profiles), useValue: { findOne: jest.fn().mockResolvedValue({ id: 1, user: {}, avatar: {} }) } }
内容的提问来源于stack exchange,提问作者Benjoe Carandang
相关产品推荐
相关产品推荐

