如何使用 jest 测试服务 (NestJS) 中的模型 (Mongoose)

Lau*_*ois 2 mongoose node.js jestjs nestjs

我有一个用 NestJS 完成的后端。在我的服务中,我注入了两个 Mongoose 模型。我使用 Jest 来测试该服务。模型按原样声明并注入到模块中:

quizes.providers.ts
import { Connection } from 'mongoose';
import { QuizSchema } from './schemas/quiz.schema';

export const quizesProviders = [
  {
    provide: 'CLASS_MODEL',
    useFactory: (connection: Connection) => connection.model('Quiz', QuizSchema),
    inject: ['DATABASE_CONNECTION'],
  },
];

users.providers.ts
import { Connection } from 'mongoose';
import { UserSchema } from './schemas/user.schema';

export const usersProviders = [
  {
    provide: 'USER_MODEL',
    useFactory: (connection: Connection) => connection.model('User', UserSchema),
    inject: ['DATABASE_CONNECTION'],
  },
];
Run Code Online (Sandbox Code Playgroud)

模块示例:

quizes.module.ts
import { Module } from '@nestjs/common';
import { QuizesController } from './quizes.controller';
import { QuizesService } from './quizes.service';

import { quizesProviders } from './quizes.providers';

import { usersProviders } from '../auth/users.providers';

import { DatabaseModule } from 'src/database.module';
import { AuthModule } from 'src/auth/auth.module';

@Module({
  imports: [DatabaseModule, AuthModule],
  controllers: [QuizesController],
  providers: [QuizesService,
  ...quizesProviders, ...usersProviders]
})
export class QuizesModule {}
Run Code Online (Sandbox Code Playgroud)

然后在我的服务中,我注入模型:

quizes.service.ts
@Injectable()
export class QuizesService {
    constructor(
        @Inject('CLASS_MODEL')
        private classModel: Model<Quiz>,
        @Inject('USER_MODEL')
        private userModel: Model<User>
      ) {}
Run Code Online (Sandbox Code Playgroud)

在我的 quiizes.spec.ts(开玩笑)中,我开始做类似的事情。它编译但不起作用:

import { Test } from '@nestjs/testing';
import * as mongoose from 'mongoose';
import { User } from 'src/auth/user.interface';
import { Quiz } from './quiz.interface';
import { databaseProviders } from '../database.providers';

const USER_MODEL:mongoose.Model<User> =  mongoose.model('User', UserSchema);

const CLASS_MODEL:mongoose.Model<Quiz> =  mongoose.model('Quiz', QuizSchema);

const mockingQuizModel = () => {
  find: jest.fn()
}

const mockingUserModel = () => {
 find: jest.fn()
}

const mockUser = {
  username: 'Test user'
}

describe('QuizesService', () => {
    let quizesService;
    let userModel , classModel;


    beforeEach(async () => {
        const module = await Test.createTestingModule({

            providers: [QuizesService, ...usersProviders, ...quizesProviders,...databaseProviders,
            {provide: USER_MODEL, useFactory: mockingUserModel},
            {provide: CLASS_MODEL, useFactory: mockingQuizModel},
        ],
        }).compile();

        quizesService = await module.get<QuizesService>(QuizesService);
        classModel = await module.get<mongoose.Model<Quiz>>(CLASS_MODEL)
        userModel = await module.get<mongoose.Model<User>>(USER_MODEL)

    })

    describe('getAllQuizes', ()=> {

        it('get all quizes', () => {
           expect(userModel.find).not.toHaveBeenCalled();
        })

    })
})
Run Code Online (Sandbox Code Playgroud)

userModel未定义并且测试不会退出。

Fra*_*oso 5

使用NestJS 官方定义的getModelToken函数: https://docs.nestjs.com/v6/ Techniques -> Mongo(向下滚动到测试部分)

那么你的代码应该看起来有点像这样:

import { getModelToken } from '@nestjs/mongoose';

const mockRepository = {
    find() {
      return {};
    }
  };

const module = await Test.createTestingModule({    
    providers: [ ...,
    {provide: getModelToken('CLASS_MODEL'), useValue: mockRepository,},
    {provide: getModelToken('USER_MODEL'), useValue: mockRepository,},
],
...
Run Code Online (Sandbox Code Playgroud)