I'm trying to write a unit test, but I had some trouble when I defined TestingModule.
i cannot create testing module in unit test because the module which i using in a 3rd library https://github.com/hardyscc/nestjs-dynamoose
Here now, it cannot support me defining modules in unit tests.
Please, someone can give me a solution.
P/s: Error in the end of the post
Thank you a lot.
here is my spect.ts file
describe('MissionService', () => {
let service: MissionService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MissionService],
}).compile();
service = module.get<MissionService>(MissionService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
here is my module
@Module({
imports: [DynamooseModule.forFeature([MissionModel])],
controllers: [MissionControllerAdmin],
providers: [MissionService, MissionRepository],
exports: [MissionService, MissionRepository],
})
export class MissionModule {}
here is my DynamooseModule
@Module({})
export class DynamooseModule {
static forRoot(options: DynamooseModuleOptions = {}): DynamicModule {
return {
module: DynamooseModule,
imports: [DynamooseCoreModule.forRoot(options)],
};
}
static forRootAsync(options: DynamooseModuleAsyncOptions): DynamicModule {
return {
module: DynamooseModule,
imports: [DynamooseCoreModule.forRootAsync(options)],
};
}
static forFeature(models: ModelDefinition[] = []): DynamicModule {
const providers = createDynamooseProviders(models);
return {
module: DynamooseModule,
providers: providers,
exports: providers,
};
}
static forFeatureAsync(factories: AsyncModelFactory[] = []): DynamicModule {
const providers = createDynamooseAsyncProviders(factories);
const imports = factories.map((factory) => factory.imports || []);
const uniqImports = new Set(flatten(imports));
return {
module: DynamooseModule,
imports: [...uniqImports],
providers: providers,
exports: providers,
};
}
}
export function createDynamooseProviders(models: ModelDefinition[] = []) {
const providers = (models || []).map((model) => ({
provide: getModelToken(model.name),
useFactory: () => {
const modelInstance = dynamoose.model(
model.name,
model.schema,
model.options,
);
if (model.serializers) {
Object.entries(model.serializers).forEach(([key, value]) => {
modelInstance.serializer.add(key, value);
});
}
return modelInstance;
},
inject: [DYNAMOOSE_INITIALIZATION],
}));
return providers;
}
dynamoose-core.module
async function initialization(options: DynamooseModuleOptions) {
if (options.ddb) {
aws.ddb.set(options.ddb);
} else if (options.aws) {
aws.ddb.set(new aws.ddb.DynamoDB(options.aws));
}
if (options.local) {
if (typeof options.local === 'boolean') {
aws.ddb.local();
} else {
aws.ddb.local(options.local);
}
}
if (options.table) {
Table.defaults.set(options.table);
}
if (options.logger) {
(await logger()).providers.add(
new LoggerProvider(
typeof options.logger === 'boolean'
? new Logger(DynamooseModule.name)
: options.logger,
),
);
}
}
@Global()
@Module({})
export class DynamooseCoreModule {
static forRoot(options: DynamooseModuleOptions = {}): DynamicModule {
const initialProvider = {
provide: DYNAMOOSE_INITIALIZATION,
useFactory: () => initialization(options),
};
return {
module: DynamooseCoreModule,
providers: [initialProvider],
exports: [initialProvider],
};
}
static forRootAsync(options: DynamooseModuleAsyncOptions): DynamicModule {
const initialProvider = {
provide: DYNAMOOSE_INITIALIZATION,
useFactory: (dynamoooseModuleOptions: DynamooseModuleOptions) =>
initialization(dynamoooseModuleOptions),
inject: [DYNAMOOSE_MODULE_OPTIONS],
};
const asyncProviders = this.createAsyncProviders(options);
return {
module: DynamooseCoreModule,
imports: options.imports,
providers: [...asyncProviders, initialProvider],
exports: [initialProvider],
};
}
private static createAsyncProviders(
options: DynamooseModuleAsyncOptions,
): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}
const useClass = options.useClass as Type<DynamooseOptionsFactory>;
return [
this.createAsyncOptionsProvider(options),
{
provide: useClass,
useClass,
},
];
}
private static createAsyncOptionsProvider(
options: DynamooseModuleAsyncOptions,
): Provider {
if (options.useFactory) {
return {
provide: DYNAMOOSE_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
const inject = [
(options.useClass ||
options.useExisting) as Type<DynamooseOptionsFactory>,
];
return {
provide: DYNAMOOSE_MODULE_OPTIONS,
useFactory: async (optionsFactory: DynamooseOptionsFactory) =>
await optionsFactory.createDynamooseOptions(),
inject,
};
}
}
async function initialization(options: DynamooseModuleOptions) {
if (options.ddb) {
aws.ddb.set(options.ddb);
} else if (options.aws) {
aws.ddb.set(new aws.ddb.DynamoDB(options.aws));
}
if (options.local) {
if (typeof options.local === 'boolean') {
aws.ddb.local();
} else {
aws.ddb.local(options.local);
}
}
if (options.table) {
Table.defaults.set(options.table);
}
if (options.logger) {
(await logger()).providers.add(
new LoggerProvider(
typeof options.logger === 'boolean'
? new Logger(DynamooseModule.name)
: options.logger,
),
);
}
}
i tried import like i used in module. but it seem not work
import { DynamooseModule } from './../configuration/dynamoose/dynamoose.module';
import { Test, TestingModule } from '@nestjs/testing';
import { MissionService } from './mission.service';
import { MissionModel } from './entities/mission.entity';
describe('MissionService', () => {
let service: MissionService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [DynamooseModule.forFeature([MissionModel])],
providers: [MissionService],
}).compile();
service = module.get<MissionService>(MissionService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
most common error i got
FAIL src/mission/mission.service.spec.ts
MissionService
✕ should be defined (7 ms)
● MissionService › should be defined
Nest can't resolve dependencies of the missionsModel (?). Please make sure that the argument DynamooseInitialiation at index [0] is available in the DynamooseModule context.
Potential solutions:
- Is DynamooseModule a valid NestJS module?
- If DynamooseInitialiation is a provider, is it part of the current DynamooseModule?
- If DynamooseInitialiation is exported from a separate @Module, is that module imported within DynamooseModule?
@Module({
imports: [ /* the Module containing DynamooseInitialiation */ ]
})
9 |
10 | beforeEach(async () => {
> 11 | const module: TestingModule = await Test.createTestingModule({
| ^
12 | imports: [DynamooseModule.forFeature([MissionModel])],
13 | providers: [MissionService],
14 | }).compile();