Mock multiple TypeORM repositories in NestJS - node.js

I'm having trouble to mock multiple repositories from different modules in NestJS.
I'm using a UsersRepository from a UsersModule inside another module service (NotesService). The code is working fine, but I can't make the unit tests work.
I have the following error: Error: Nest can't resolve dependencies of the UserRepository (?). Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context.
Minimal reproduction
// [users.module.ts]
#Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
// [users.service.ts]
#Injectable()
export class UsersService {
constructor(#InjectRepository(User) private usersRepository: UsersRepository) {}
...
}
// [notes.module.ts]
#Module({
imports: [
TypeOrmModule.forFeature([Note, User]),
UsersModule,
],
controllers: [NotesController],
providers: [NotesService],
})
export class NotesModule {
}
// [notes.service.ts]
#Injectable()
export class NotesService {
constructor(
#InjectRepository(Note) private notesRepository: NotesRepository,
#InjectRepository(User) private usersRepository: UsersRepository,
) {}
...
}
Here is my unit test configuration:
// [notes.service.spec.ts]
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [UsersModule],
providers: [
NotesService,
{ provide: getRepositoryToken(Note), useFactory: repositoryMockFactory },
{ provide: getRepositoryToken(User), useFactory: repositoryMockFactory },
],
}).compile();
notesService = module.get<NotesService>(NotesService);
notesRepositoryMock = module.get(getRepositoryToken(Note));
});
The problem is I can't make a proper mock of the UsersRepository that comes from another module.
I tried importing TypeOrmModule directly inside the test, and everything I could but I can't make it work.

You don't need to import the UsersModule if you are directly providing the NotesService and the mocks that it will depend on. The reason for the error is that Nest is trying to resolve TypeormModule.forFeature([User]) from the UsersModule. Simply remove the import in the test and you should be golden.

Related

Nestjs modules - shared custom provider is not working

I have a proyect with multiple modules, and all of them need the same provider, then I have used a shared module but I don't know where the mistake is
import { Module } from '#nestjs/common';
import { ChatBot } from './chat-bot';
import { ChatBotImplementation } from './chat-bot.implementation';
#Module({
providers: [{ provide: ChatBot, useClass: ChatBotImplementation }],
exports: [ChatBot],
})
export class SharedModule {}
import { Module } from '#nestjs/common';
import { CoreService } from './core.service';
#Module({
providers: [CoreService],
})
export class CoreModule {}
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SharedModule } from './shared/shared.module';
import { CoreModule } from './core/core.module';
#Module({
imports: [SharedModule, CoreModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
import { Injectable } from '#nestjs/common';
import { ChatBot } from 'src/shared/chat-bot';
#Injectable()
export class CoreService {
constructor(chatBot: ChatBot) {
chatBot.send('hola');
}
}
When I start the server, it throws this error:
[Nest] 8456 - 29/12/2022, 17:21:08 ERROR [ExceptionHandler] Nest can't resolve dependencies of the CoreService (?). Please make sure that the argument ChatBot at index [0] is available in the CoreModule context.
Potential solutions:
- Is CoreModule a valid NestJS module?
- If ChatBot is a provider, is it part of the current CoreModule?
- If ChatBot is exported from a separate #Module, is that module imported within CoreModule?
#Module({
imports: [ /* the Module containing ChatBot */ ]
})
ChatBot is an abstract class and ChatBotImplementation implements ChatBot abstract class, I have tried with symbol as provide but it don't working either. If I put the provider in the same module that use it then it works, I supose that the misteka should be in the, exports part?
Your CoreModule doesn't have the SharedModule in its imports so it doesn't have access to providers from the SharedModule's exports. Add imports: [SharedModule] to the CoreModule's module metadata and you'll be good to go

NestJS -- JWT Dependency is not being loaded

I do not need complete passport, I just need to sign a JWT token.
I tried working with this repository
I tried all possible combinations, but I just cant integrate it in the project. I had followed the course of several different errors. I fix one, and the another pops up. So, I am including minimum part, and the current error that is thrown.
AuthModule:
import { Module } from '#nestjs/common';
import { JwtModule } from '#nestjs/jwt';
import { AuthService } from './auth.service';
import { JwtService } from '#nestjs/jwt';
#Module({
imports: [ JwtModule.register({ secret: 'hard!to-guess_secret' })],
providers: [AuthService],
exports: [AuthService, JwtService]
})
export class AuthModule {}
AuthService:
import { Injectable } from '#nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '#nestjs/jwt';
#Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService,
) {}
async signPayload (user: any) {
const payload = { username: 'HARDCORE', color:'RED' };
return {
whatever: this.jwtService.sign(payload),
};
}
}
AppModule:
#Module({
imports: [
ConfigModule.forRoot(),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
secret: 'wefwefwef',
}),
inject: [ConfigService],
}),
TypeOrmModule.forRoot({
type: 'mysql',
...
}),
UsersModule,
SubscriptionsModule,
ProductsModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
SomeController:
export class UsersController {
constructor(private readonly usersService: UsersService,
private readonly authService: AuthService
) {}
...
#ApiResponse({ status: 401, description: 'Unauthorized.' })
#ApiResponse({ status: 404, description: 'User Not Found.' })
#Get('users')
async findOne(#Query() userGetDto: UserGetDto): Promise<User> {
const user = await this.usersService.findByUsername(userGetDto.userName);
if (!user) throw new NotFoundException('User Not Found')
let signedUser = this.authService.signPayload(user);
return user;
And this is the error with this setup that I get:
Nest can't resolve dependencies of the JwtService (?). Please make
sure that the argument JWT_MODULE_OPTIONS at index [0] is available in
the JwtService context.
I spend lot of time on this one, but I just cant make it work.
Based on your error, JwtService is in an imports array somewhere. Providers (classes marked with #Injectable()) never go in the imports array, but rather should be added to the exports array and that module where the exports was added should be put in the consuming module's imports array.
Also, if you are working with a Dynamic Module (any module that uses register or forRoot or an async variant of the two) you should always export the module instead of its services, as the module most likely has important configurations necessary for the service to work.

NestJs monorepo shared lib injection

I have NestJS application with couple microservices stored in single repository (monorepo approach).
AccessControl module stores in libs, it should be shared across multiple microservices. It has AccessControlModule.ts file
#Global()
#Module({
providers: [
{
provide: 'CONNECTION1',
useFactory: (configService: ConfigService) => {
return ClientProxyFactory.create(
configService.getRMQConnection(),
);
},
inject: [ConfigService],
},
ACGuard,
],
exports: [ACGuard],
imports: [ConfigModule],
})
export class AccessControlModule implements OnModuleDestroy {
constructor(
#Inject('CONNECTION1')
protected readonly orgConnection: ClientProxy,
) {}
onModuleDestroy(): any {
this.orgConnection.close();
}
}
This file responsible for module description, it creates connection for another microservice and provide it to ACGuard service. ACGuard.ts:
#Injectable()
export class ACGuard implements CanActivate {
constructor(
private readonly reflector: Reflector,
private config: ConfigService,
#Inject('CONNECTION1')
private readonly userConnection: ClientProxy;
) {}
public async canActivate(context: ExecutionContext): Promise<boolean> {
// do some stuff
}
}
This part by itself compiles well and logically works fine. Problem begins when I try to inject it into one of microservices. I do it as usual by adding AccessControlModule into import part of some module. For example KioskModule:
#Module({
imports: [
...
AccessControlModule
],
providers: [
...
KiosksResolver
]
})
export class KiosksModule {}
Since AccessControlModule marked as Global and exports ACGuard I expect it to be injectable into my providers.
#Resolver('Kiosk')
export class KiosksResolver {
...
#UseGuards(ACGuard)
#Query()
kiosks() {
// ...
}
...
}
But this code falls on the compilation step with error:
[Nest] 9964 - 05/07/2020, 9:33:02 PM [ExceptionHandler] Nest can't resolve dependencies of the ACGuard (Reflector, ConfigService, ?). Please make sure that the argument CONNECTION1 at index [2] is available in the KiosksModule context.
On the other hand, if i inject it in KiosksResolver's constructor, application builds successfully.
I will appreciate any help and ideas, thanks!
The way how i solved this issue was exporting CONNECTION1 provider in AccessControlModule.ts.
#Module({
providers: [
{
provide: 'CONNECTION1',
useFactory: (configService: ConfigService) => {
return ClientProxyFactory.create(
configService.getRMQConnection(),
);
},
inject: [ConfigService],
},
ACGuard,
],
exports: [ACGuard, 'CONNECTION1'],
imports: [ConfigModule],
})
export class AccessControlModule ...
With this export KioskModule creates it's own ACGuard but provides here connection exported from AccessControlModule.
It's not clear for me why KioskModule doesn't get built instance of ACGuard exported from AccessControlModule but try build it once more.

NestJS cannot resolve my UsersService dependency why? Is it due to UserModel?

I am trying to learn NodeJS framework. I have initialized a project for that and now I am trying to add authentication to secure the HTTP access. I follows the NestJS documentation but I have the following error when I inject my UsersService in the AuthService:
[Nest] 14876 - 13/04/2020 à 09:26:19 [ExceptionHandler] Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument UserModel at index [0] is available in the AuthModule context.
Potential solutions:
- If UserModel is a provider, is it part of the current AuthModule?
- If UserModel is exported from a separate #Module, is that module imported within AuthModule?
#Module({
imports: [ /* the Module containing UserModel */ ]
})
+2ms
Error: Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument UserModel at index [0] is available in the AuthModule context.
It seems that it is due to the following injection in my UsersService :
constructor(#InjectModel('User') private readonly UserModel: Model) {}
but I doesn't know how to solve this problem. My training project is stored on github :
https://github.com/afontange/nest-js.git
I read other tickets on same subject but I don't know what is the solution for my problem.
Thanks for your help.
export const UsersSchema = new Schema({
name: String,
});
Module({
imports: [
MongooseModule.forFeature([{ name: 'Users', schema: UsersSchema }]) // add
],
controllers: [],
providers: [],
exports: []
})
export class AuthModule {}
Do you add in your Auth.module.ts
The AuthModule is the following:
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '#nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { UsersService } from '../users/users.service';
#Module({
imports: [UsersModule, PassportModule],
providers: [AuthService, LocalStrategy, UsersService],
})
export class AuthModule {}

Nest can't resolve dependencies of the ProductModel (?)

I am trying to implement Mongoose crud service. I am missing something on injecting model or injecting module.
I am getting below error:
Nest can't resolve dependencies of the ProductModel (?). Please make sure that the argument DatabaseConnection at index [0] is available in the MongooseModule context
app.module.ts
#Module({
imports: [ProductsModule,
MongooseModule.forRoot(config.mongoURI)],
})
export class AppModule { }
product.module.ts
#Module({
imports: [MongooseModule.forFeature([{ name: 'MyProduct', schema: ProductSchema }])],
controllers: [ProductsController],
providers: [ProductsService],
exports: [ProductsService]
})
export class ProductsModule { }
product.service.ts
#Injectable()
export class ProductsService extends GenericMongooseCrudService<IProduct> {
eventEmitter: EventEmitter = new EventEmitter();
#InjectModel('MyProduct') private readonly userModel: Model<IProductModel>;
}
product.interface.ts
export interface IProduct extends IModelInstance {
value: string
}
export interface IProductModel extends IProduct, IMongoDocument {
}

Resources