How do I use UserDocument/UserModel in jest Testcases using NestJs

Viewed 417

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: 'demo@gmail.com',
        password: 'demo@123',
        role: 'user'
      })
    ).toEqual({
      statusCode: 201,
      message: 'User created successfully',
      data: {
        isActive: true,
        role: 'user',
        password:
          '$2b$10$VjwR0Wjf6vTaRjQlsizB5OLY04NJOcRyC/pPLbTPTQnWTDIrBU.Sq',
        email: 'demo@gmail.com',
        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.

2 Answers

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: 'demo@gmail.com',
  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()
  })
  
})

Related