I have been getting issues with the injections of Nest.js when working with TestingModule
. The app works fine when ran but not through the tests. The issue happens when trying to get any other provider the UserRepositoryProvider
from the AppModule
which is imported into the TestModule
.
Nest could not find PrismaService element (this provider does not exist in the current context)
test/user.integration.spec.ts:
describe("User Controller", () => {
let app: INestApplication;
let userRepository: UserRepository;
beforeEach(async () => {
const moduleRef: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
userRepository = moduleRef.get("UserRepository"); // works
const prisma = moduleRef.get(PrismaService); // doesn't work
console.log(prisma);
app = moduleRef.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
src/app-module.ts:
const controllers = [HealthCheckController, UserController];
const providers = [UserRepositoryProvider];
const services = [PrismaService];
const useCases = [RegisterUserUseCase, GetUserInfosUseCase];
@Module({
imports: [],
controllers: controllers,
providers: [...providers, ...services, ...useCases],
exports: [...providers, ...services, ...useCases],
})
export class AppModule {}
src/infrastructure/persistence/user/user.repository.provider.ts
import { PrismaUserAdapter } from "./user.prisma.adapter";
export const UserRepositoryProvider = {
provide: "UserRepository",
useClass: PrismaUserAdapter,
};
src/infrastructure/persistence/prisma.service.ts:
import { Injectable, OnModuleInit, OnModuleDestroy } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
constructor() {
super({
datasources: {
db: {
url:
process.env.NODE_ENV === "production"
? process.env.DATABASE_URL
: process.env.DATABASE_URL_DEV,
},
},
});
}
async onModuleInit() {
let retries = 5;
while (retries > 0) {
try {
await this.$connect();
console.log("Database connection established.");
break;
} catch (error) {
retries--;
console.log(`Retrying database connection (${5 - retries}/5)...`);
if (retries === 0) {
throw error;
}
await new Promise((res) => setTimeout(res, 5000)); // Wait 5 seconds before retrying
}
}
}
async onModuleDestroy() {
await this.$disconnect();
}
}
And this is happening for any @Injectable
class I’ve made.
I tried to implement OnModuleInit()
on all the classes and log a message when it’s initialized
I logged the injected classes in the some constructor, and they were undefined
I tried set up the providers with Tokens but same results
LyingPasta is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.