You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级TypeORM 0.3.12后NestJS自定义Repository方法调用失败

NestJS升级TypeORM 0.3.12后E2E测试报错的解决方法

问题背景

  • 已完成NestJS项目到TypeORM 0.3.12的升级,所有集成测试(如TypeOrmAthleteRepository相关测试)已修复并可正常通过
  • 运行E2E测试时触发两个关键错误:
    • [ExceptionHandler] this.athleteRepository.findByEmail is not a function
    • EntityMetadataNotFoundError: No metadata for "TypeOrmAthleteRepository" was found

排查与解决方法

1. 自定义仓库注入逻辑错误

TypeORM 0.3.x对自定义仓库的注入规则有调整,E2E测试中可能误将仓库类当作实体注入,而非通过正确方式获取实例。

修正步骤:

  • 服务类中确保用@InjectRepository()正确注入自定义仓库:
    import { Injectable } from '@nestjs/common';
    import { InjectRepository } from '@nestjs/typeorm';
    import { TypeOrmAthleteRepository } from './typeorm-athlete.repository';
    
    @Injectable()
    export class AthleteService {
      constructor(
        @InjectRepository(TypeOrmAthleteRepository)
        private readonly athleteRepository: TypeOrmAthleteRepository,
      ) {}
    
      async findByEmail(email: string) {
        return this.athleteRepository.findByEmail(email);
      }
    }
    
  • 自定义仓库需正确继承Repository并关联实体:
    import { Repository } from 'typeorm';
    import { Athlete } from './athlete.entity';
    
    // TypeORM 0.3.x已废弃@EntityRepository,直接继承Repository即可
    export class TypeOrmAthleteRepository extends Repository<Athlete> {
      async findByEmail(email: string) {
        return this.findOne({ where: { email } });
      }
    }
    

2. AppModule配置错误

检查AppModule的TypeORM配置,确认实体路径正确,且自定义仓库已正确注册。

正确配置示例:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Athlete } from './athlete.entity';
import { TypeOrmAthleteRepository } from './typeorm-athlete.repository';
import { AthleteService } from './athlete.service';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'password',
      database: 'test',
      entities: [Athlete], // 这里只注册实体,不要注册仓库类
      synchronize: true,
    }),
    TypeOrmModule.forFeature([Athlete, TypeOrmAthleteRepository]), // 同时注册实体和自定义仓库
  ],
  providers: [AthleteService],
  exports: [AthleteService],
})
export class AppModule {}

3. E2E测试模块配置遗漏

E2E测试模块可能未正确导入TypeORM配置或自定义仓库,导致依赖注入失败。

测试模块修正示例:

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AthleteService } from '../src/athlete.service';
import { TypeOrmAthleteRepository } from '../src/typeorm-athlete.repository';
import { Athlete } from '../src/athlete.entity';

describe('Athlete E2E', () => {
  let app: INestApplication;
  let athleteService: AthleteService;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [
        TypeOrmModule.forRoot({
          type: 'postgres',
          host: 'localhost',
          port: 5432,
          username: 'postgres',
          password: 'password',
          database: 'test_e2e',
          entities: [Athlete],
          synchronize: true,
          dropSchema: true, // 测试前清空数据库
        }),
        TypeOrmModule.forFeature([TypeOrmAthleteRepository]),
      ],
      providers: [AthleteService],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();

    athleteService = moduleFixture.get<AthleteService>(AthleteService);
  });

  afterEach(async () => {
    await app.close();
  });

  it('should find athlete by email', async () => {
    const email = 'test@example.com';
    const result = await athleteService.findByEmail(email);
    expect(result).toBeDefined();
  });
});

4. 适配@EntityRepository废弃规则

TypeORM 0.3.x已彻底废弃@EntityRepository装饰器,若旧代码使用了该装饰器,需替换为手动继承Repository的方式:

旧代码(需替换):

import { EntityRepository, Repository } from 'typeorm';
import { Athlete } from './athlete.entity';

@EntityRepository(Athlete)
export class TypeOrmAthleteRepository extends Repository<Athlete> {
  // ...自定义方法
}

新代码:

import { Repository, DataSource } from 'typeorm';
import { Athlete } from './athlete.entity';

export class TypeOrmAthleteRepository extends Repository<Athlete> {
  constructor(dataSource: DataSource) {
    super(Athlete, dataSource.createEntityManager());
  }

  // ...自定义方法
}

同时在模块中仅注册实体,仓库实例可通过DataSource手动生成或依赖注入获取。

内容的提问来源于stack exchange,提问作者A Mehmeto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:23:10