How can I test the Sequelize param, like
constructor(
private sequelize: Sequelize,
#InjectModel(User) private userModel: typeof User,
#InjectModel(Shop) private shopModel: typeof Shop
) {}
for the models I use
{ provide: getModelToken(User), useValue: User },
{ provide: getModelToken(Shop), useValue: Shop },
How can I add Sequelize as provider?
It gives me this error:
Potential solutions:
- If Sequelize is a provider, is it part of the current TestingRootModule?
- If Sequelize is exported from a separate #Module, is that module imported within TestingRootModule?
#Module({
imports: [ /* the Module containing Sequelize */ ]
})
Ok, I have found the solution, you just have to add this to the provider
{
provide: Sequelize,
useValue: sequelizeMock
}
Related
I need to use the ConfigService to get the environment variables, but when I use "forRootAsync" of the TypeOrmModule nestjs is unable to resolve the DataService dependency
This is my module
#Module({
imports: [
ConfigModule.forRoot({ validate: validateConfig(AssetEnvironmentVariables), isGlobal: true }),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService): TypeOrmModuleOptions => ({
type: "postgres",
host: configService.get("PG_HOST"),
port: configService.get("PG_PORT"),
database: configService.get("PG_DB_NAME"),
username: configService.get("PG_USER"),
password: configService.get("PG_PASSWORD"),
entities: [AssetEntity],
migrations: ["./migrations/*"],
}),
});
],
providers: [
{ provide: AssetRepository, useClass: AssetPostgresRepository },
],
})
export class AssetModule {}
This is the implementation to AssetRepository
#Injectable()
export class AssetPostgresRepository extends AssetRepository {
private typeOrmRepository: Repository<AssetEntity>;
constructor(dataSource: DataSource) {
super();
this.typeOrmRepository = dataSource.getRepository(AssetEntity);
}
async save(asset: Asset): Promise<void> {
try {
await this.typeOrmRepository.save(asset.toPrimitives());
} catch (e) {
throw new SavingRepositoryException(e);
}
}
}
This is the error that it throw me
ERROR [ExceptionHandler] Nest can't resolve dependencies of the AssetPostgresRepository (?). Please make sure that the argument DataSource at index [0] is available in the AssetModule context.
Potential solutions:
- Is AssetModule a valid NestJS module?
- If DataSource is a provider, is it part of the current AssetModule?
- If DataSource is exported from a separate #Module, is that module imported within AssetModule?
#Module({
imports: [ /* the Module containing DataSource */ ]
})
I have created a custom provider in one of my modules.
I need to export that custom provider to make it available in other modules and I'm having trouble doing so. I do not know what to put in the exports array.
Below is my custom provider.
#Module({
imports: [TypeOrmModule.forFeature([TypeOrmUser])],
providers: [
UserMapper,
UserService,
{
provide: getRepositoryToken(TypeOrmUser),
inject: [getDataSourceToken()],
useFactory(dataSource: DataSource) {
return dataSource.getRepository(TypeOrmUser).extend(userRepositoryImpl);
},
},
],
exports: [UserService, 'what to put here to export custom user repository?'],
})
export class UsersModule {}
Thank you for your help.
To export a custom provider, all that is needed to be added to the exports array is the provider's injection token.
In this case, that's getRepositoryToken(TypeOrmUser)
You can export it either with token name, or with the whole provider object. In your case it would be something like this:
exports: [UserService, getRepositoryToken(TypeOrmUser)],
or:
const customProvider = {
provide: getRepositoryToken(TypeOrmUser),
inject: [getDataSourceToken()],
useFactory(dataSource: DataSource) {
return dataSource.getRepository(TypeOrmUser).extend(userRepositoryImpl);
},
};
#Module({
imports: [TypeOrmModule.forFeature([TypeOrmUser])],
providers: [
UserMapper,
UserService,
customProvider,
],
exports: [UserService, customProvider],
})
In a NestJs project, I created a module that uses, DiscoveryService in the services. It working fine. I wanted to create a nest library from that module. I followed this nestJs documentation then I am getting the below error. I tried both adding ModulesContainer in to my module imports and providers. nothing helped.
[Nest] 65775 - 10/12/2022, 11:55:03 AM ERROR [ExceptionHandler] Nest can't resolve dependencies of the DiscoveryService (?). Please make sure that the argument ModulesContainer at index [0] is available in the DiscoveryModule context.
Error log
Potential solutions:
If ModulesContainer is a provider, is it part of the current DiscoveryModule?
If ModulesContainer is exported from a separate #Module, is that module imported within DiscoveryModule? #Module({
imports: [ /* the Module containing ModulesContainer */ ] })
Error: Nest can't resolve dependencies of the DiscoveryService (?).
Please make sure that the argument ModulesContainer at index [0] is
available in the DiscoveryModule context.
library
import { DiscoveryService } from '#nestjs/core';
#Injectable()
export class EventPublishingService {
private readonly logger = new Logger(EventPublishingService.name);
private readonly publishingEventProviders;
constructor(
private discoveryService: DiscoveryService
) {
this.publishingEventProviders = this.discoveryService
.getProviders()
.filter(
({ metatype }) =>
metatype && Reflect.getMetadata(PUBLISHABLE_METADATA, metatype),
);
}
}
#Global()
#Module({
imports: [DiscoveryModule, HttpModule, ConfigModule],
providers: [
EventRegistrationService,
EventManagerServiceApi,
EventPublishingService],
exports: [EventPublishingService],
})
export class EventManagerModule {}
app module
#Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
load: [configuration],
}),
ScheduleModule.forRoot(),
MongooseModule.forRootAsync({
imports: [DataVaultManagerModule],
inject: [DataVaultManager],
useClass: MongooseConfigService,
}),
ParticipantsModule,
StudiesModule,
HealthModule,
EventManagerModule,
UsersModule,
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_PIPE,
useClass: ZodValidationPipe,
},
],
})
export class AppModule {}
Try changing constructor from EventPublishingService class like below:
constructor(
#Inject(DiscoveryService) private discoveryService: DiscoveryService
)
I am writing end-to-end tests in NestJs and using the "overrideProvider" function to setup test versions of various services (e.g. services that require database connections). I noticed though that even when I do this, the original implementation that injects the real database is still instantiated.
Is there a way to tell Nest to not create transitive dependencies that are overridden?
For example, I have a test that starts like:
...
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [ServiceModule],
})
// Works if I uncomment these lines:
// .overrideProvider('Database')
// .useValue(new TestDatabase())
.overrideProvider('ServiceUsingDatabase')
.useValue(new TestService())
.compile();
...
Where the module setup is like:
import { Inject, Injectable, Module } from '#nestjs/common';
interface Database {}
#Injectable()
class ProductionDatabase implements Database {
constructor() {
throw('Cannot create a production database.');
}
}
#Injectable()
export class TestDatabase implements Database {
constructor() {
console.log('Creating the test database.');
}
}
#Module({
providers: [
{
provide: 'Database',
useClass: ProductionDatabase
}
],
exports: ['Database']
})
class DatabaseModule {}
interface Service {}
#Injectable()
class ProductionService implements Service {
constructor(#Inject('Database') private readonly database: Database) {}
}
#Injectable()
export class TestService implements Service {
// Test implementation of the service does not Inject anything.
}
#Module({
imports: [DatabaseModule],
providers: [
{
provide: 'ServiceUsingDatabase',
useClass: ProductionService
}
],
})
export class ServiceModule {}
But, the DI system is still seeming to try and instantiate ProductionDatabase. If I explicitly override the provider for the 'Database' it works, but I'd like to avoid having to explicitly list all transitive dependencies as such.
I ended up deciding to make a "Test" Module for every Module e.g.:
import { Inject, Injectable, Module } from '#nestjs/common';
interface Database {}
#Injectable()
class ProductionDatabase implements Database {
}
#Injectable()
export class TestDatabase implements Database {
}
#Module({
providers: [
{
provide: 'Database',
useClass: ProductionDatabase
}
],
exports: ['Database']
})
class DatabaseModule {}
#Module({
providers: [
{
provide: 'Database',
useClass: TestDatabase
}
],
exports: ['Database']
})
class TestDatabaseModule {}
interface Service {}
#Injectable()
class ProductionService implements Service {
constructor(#Inject('Database') private readonly database: Database) {}
}
#Injectable()
export class TestService implements Service {
}
#Module({
imports: [DatabaseModule],
providers: [
{
provide: 'ServiceUsingDatabase',
useClass: ProductionService
}
],
})
export class ServiceModule {}
#Module({
providers: [
{
provide: 'ServiceUsingDatabase',
useClass: TestService
}
],
})
export class TestServiceModule {}
etc... Though it turned out after some refactorings that the "Test" module wasn't needed as some Modules became pure business logic.
After configured cache globally like the docs, the CacheInterceptor throws an error if i use it outside the app.module.
app.module.ts
const cacheConfig = {
store: redisStore,
host: 'localhost',
port: 6379
}
#Module({
imports: [
CacheModule.register(cacheConfig),
CustomerModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor
}
]
})
export class AppModule {}
customer.module.ts
#Module({
imports: [TypeOrmModule.forFeature([CustomerRepository]), TypeOrmModule.forFeature([User])],
controllers: [CustomerController]
})
export class CustomerModule {}
customer.controller.ts
#Controller('customer')
export class CustomerController {
constructor(
#InjectRepository(CustomerRepository) private customerRepository: CustomerRepository,
#InjectRepository(User) private userRepository: Repository<User>
) {}
#Get()
#UseInterceptors(CacheInterceptor)
async get(): Promise<any> {
const user = await this.userRepository.findOne({ where: { id: 1 }, relations: ['customer'] })
console.log(user.customer.name)
const customer = await this.customerRepository.findOne({ where: { id: 1 }, select: ['id', 'name'] })
return { customer: customer.name, email: user.email }
}
}
I would like using the CacheInterceptor along any modules without import the CacheModule each one.
Nest can't resolve dependencies of the APP_INTERCEPTOR (UUID: 6aa42c77-1bac-4098-b217-1b01eb268240) (?, Reflector). Please make sure that the argument at index [0] is available in the CustomerModule context.
If you have { provide: APP_INTERCEPTOR, useClass: CacheInterceptor } you don't need to add in the #UseInterceptors() decorator in your controller. You should have the CahceInterceptor working by default with the rest of the set up