InjectRepository not working for custom repositories in v8
fhervieux opened this issue · comments
I'm submitting a...
[x] Regression
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
While trying to migrate an application from v7 to v8 I stumbled upon a change of behavior that looks like a regression. I have a custom repository that I want to inject in a service with @InjectRepository
. Nest fails with an error "Nest can't resolve dependencies of the XxxService". The change of behavior seems to come from getRepositoryToken
that used to return a string for a custom repository and now returns the object itself (here: https://github.com/nestjs/typeorm/blob/master/lib/common/typeorm.utils.ts#L39).
Expected behavior
I am not sure if returning something else that a string is valid as a token. It seemed to work fine in v7 with a string that is all I can say. Moreover removing the @InjectRepository
works but it comes with another issue: when mocking in tests the best practice still seems to be using getRepositoryToken
(https://docs.nestjs.com/techniques/database#testing) which in this case returns a string so it only works with the annotation.
Minimal reproduction of the problem with instructions
The issue can be reproduced with a simple entity repository
@EntityRepository(Cat)
export class CatRepository extends Repository<Cat> {}
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
entities: [Cat],
}),
TypeOrmModule.forFeature([CatRepository]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Nest will fail to resolve the dependencies of this service:
@Injectable()
export class AppService {
constructor(
@InjectRepository(Cat)
private readonly catRepository: CatRepository,
) {}
}
What is the motivation / use case for changing the behavior?
Environment
Nest version: 8.0.6
Nest/TypeOrm version : 8.0.2
For Tooling issues:
- Node version: v14.15.5
- Platform: Mac
Others:
If you remove the @InjectRepository(Cat)
(since you're using a custom repository, you don't need this) it will work?
Removing @InjectRepository(Cat)
will work when starting the app. However then unit tests do no work anymore. I do something along those lines in my tests:
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [
AppService,
{
provide: getRepositoryToken(Cat),
useValue: {},
},
],
}).compile();
If I remove @InjectRepository(Cat)
then this will fail with the same error: "Nest can't resolve dependencies of the AppService". It works if I keep the annotation.
what if you change getRepositoryToken(Cat)
to getRepositoryToken(CatRepository)
?
Indeed in v8 you can't use getRepositoryToken(Entity)
if you don't annotate with @InjectRepository(Entity)
. But this is what the docs already states.
I'd say: remove all your @InjectRepository(Entity)
if you're using custom repo and use getRepositoryToken(YourCustomRepo)
.
In v8, you should be able to replace this:
@Injectable()
export class AppService {
constructor(
@InjectRepository(Cat)
private readonly catRepository: CatRepository,
) {}
}
with this:
@Injectable()
export class AppService {
constructor(
private readonly catRepository: CatRepository,
) {}
}
as for unit tests, change this:
{
provide: getRepositoryToken(Cat),
useValue: {},
},
to this:
{
provide: CatRepository,
useValue: {},
},