node.js - Hur använder jag UserDocument/UserModel i jest-testfall med NestJs
Jag försöker lägga till verkligt värde i databasen med NestJS med Jest-testfall.
Huvudsyftet med testfall är att faktiskt kontrollera databasvärden som skrivs och hämtas från databasen. Så jag mockar inga save eller find-metoder eftersom jag vill göra den faktiska anslutningen till databasen och hämta poster därifrån. Utan att mocka save() och find()-metoderna kan jag inte köra testfallen. Kompileringen misslyckas utan dem.
Jag sitter fast med filen users.service.spec.tsUserDocument och dess metoder 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 ',
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 ',
name: 'demouser',
_id: expect.any(Number)
}
})
})
})
Som jag har påpekat i specifikationsfilen är UserDocument typen som definieras i filen users.entity.ts, värdet UserDocument accepteras inte i raden userDocument=module.get<UserDocument>(UserDocument).
Svar #1
Jag löste mitt problembaserade fel.
Genom att lägga till denna import löstes mitt fel.
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])Jag kan lägga till det faktiska värdet i databasen
//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 ',
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()
})
})
Svar #2
userDocument=module.get<UserDocument>(UserDocument) måste vara
userDocument=module.get<UserDocument>(getModelToken(User.name))
eftersom du försöker hämta stubben som du har definierat för getModelToken(User.name) leverantör
I useValue: UserDocument måste du använda något stub-/mock-objekt som detta: https://github.com/jmcdo29/testing-nestjs/blob/6c77b2a5001a48673c77c9659d985a083354579f/apps/sequelize-sample/src/cats/cats.service.spec.ts#L17-L20 eftersom du försöker att inte använda den riktiga modellen.
