I am trying to add actual value to the database using nestjs with jest test cases.
The main purpose of test cases is to actually check the database values written and retrived from the database. So I'm not mocking any save
or find
method as I want to make the actual connection to the database and retrive the records from there. So without mocking the save()
and find()
methods I'm not able get the test cases running. The compilation fails without it.
I am stuck with users.service.spec.ts
file in which I want to use UserDocument
and it's methods create()
,findAll()
.
//user.entity.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
export type UserDocument = User & Document;
@Schema()
export class User {
@Prop({ unique: true })
username: string;
@Prop()
age: number;
@Prop()
password: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
// User.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { MongooseModule } from '@nestjs/mongoose'
import { User, UserSchema } from './schemas/user.schema'
import { UsersController } from './users.controller';
@Module({
imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService]
})
export class UsersModule {}
// users.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete,UseGuards } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get()
findAll() {
return this.usersService.findAll();
}
}
//users.service.ts
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { User, UserDocument } from './schemas/user.schema';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
@Injectable()
export class UsersService {
constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}
async create(createUserDto: CreateUserDto): Promise<User> {
const createdUser = new this.userModel(createUserDto);
return await createdUser.save();
}
async findAll(): Promise<User[]> {
return await this.userModel.find().exec();
}
}
//users.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing'
import { UsersService } from './users.service'
import { AppConfigModule } from '../config/app-config.module'
import { AppConfigService } from '../config/app-config.service'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { MongooseModule, getModelToken } from '@nestjs/mongoose'
import { PaginationQuery } from 'src/helpers/pagination/pagination-query.dto'
import { User, UserSchema, UserDocument } from './entities/user.entity'
describe('UsersService', () => {
let service: UsersService
let userDocument: UserDocument
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true
}),
MongooseModule.forRootAsync({
imports: [AppConfigModule],
inject: [AppConfigService],
useFactory: (config: AppConfigService) => ({
uri: `mongodb://${config.TESTDATABASE_HOST}:${config.TESTDATABSE_PORT}`,
dbName: config.TESTDATABASE_NAME
})
})
],
providers: [
UsersService,
{
provide: getModelToken(User.name),
useValue: UserDocument // <----------- Not able to understand what will go here
}
]
}).compile()
service = module.get<UsersService>(UsersService)
userDocument = module.get<UserDocument>(UserDocument) // <---- As this is type here not accepting value
})
it('should be defined', () => {
expect(service).toBeDefined()
})
it('create test data', async () => {
expect(
await service.create({
name: 'demouser',
email: '[email protected]',
password: 'demo@123',
role: 'user'
})
).toEqual({
statusCode: 201,
message: 'User created successfully',
data: {
isActive: true,
role: 'user',
password:
'$2b$10$VjwR0Wjf6vTaRjQlsizB5OLY04NJOcRyC/pPLbTPTQnWTDIrBU.Sq',
email: '[email protected]',
name: 'demouser',
_id: expect.any(Number)
}
})
})
})
As I've highlighted in the spec file, UserDocument
is the type defined in the users.entity.ts
file, the value UserDocument is not accepted in the userDocument = module.get<UserDocument>(UserDocument)
line.
CodePudding user response:
userDocument = module.get<UserDocument>(UserDocument)
must be
userDocument = module.get<UserDocument>(getModelToken(User.name))
since you're trying to get the stub that you have defined for getModelToken(User.name)
provider
In useValue: UserDocument
you must use some stub/mock object like this one: https://github.com/jmcdo29/testing-nestjs/blob/6c77b2a5001a48673c77c9659d985a083354579f/apps/sequelize-sample/src/cats/cats.service.spec.ts#L17-L20 since you're trying to not use the real model.
CodePudding user response:
I resolved my Problem Error.
Adding this import, it resolved my error.
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])
I can add the Actual value to the database
//users.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing'
import { UsersService } from './users.service'
import { AppConfigModule } from '../config/app-config.module'
import { AppConfigService } from '../config/app-config.service'
import { ConfigModule } from '@nestjs/config'
import { MongooseModule, getModelToken } from '@nestjs/mongoose'
import { User, UserSchema } from './entities/user.entity'
import { isValidObjectId } from 'mongoose'
import { HttpException } from '@nestjs/common'
const testUser = {
name: 'demouser',
email: '[email protected]',
password: 'demo@123',
role: 'user'
}
describe('UsersService', () => {
let service: UsersService
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true
}),
MongooseModule.forRootAsync({
imports: [AppConfigModule],
inject: [AppConfigService],
useFactory: (config: AppConfigService) => ({
uri: `mongodb://${config.TESTDATABASE_HOST}:${config.TESTDATABSE_PORT}`,
dbName: config.TESTDATABASE_NAME
})
}),
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])//-------import model here
],
providers: [UsersService]
}).compile()
service = module.get<UsersService>(UsersService)
})
it('should be defined', () => {
expect(service).toBeDefined()
})
})