首页 > 解决方案 > 如何在 Nestjs 服务中模拟猫鼬数据库

问题描述

我在为 nestjs 服务实施测试时遇到了麻烦。我当前的代码看起来像这样

import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Product, ProductDocument } from '../schemas/products.schema';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';

@Injectable()
export class ProductsService {
  constructor(@InjectModel(Product.name) private ProductModel: Model<ProductDocument>) {}

  create(createProductDto: CreateProductDto): Promise<Product> {
    return this.ProductModel.create(createProductDto);
  }

  findAll(): Promise<Product[]> {
    return this.ProductModel.find().exec();
  }

  findOne(id: string): Promise<Product> {
    return this.ProductModel.findById(id).exec();
  }

  update(id: string, updateProductDto: UpdateProductDto) {
    return this.ProductModel.findByIdAndUpdate(id, updateProductDto, {new: true}).exec();
  }
}

当前的测试实现看起来像这样

import { getModelToken, MongooseModule } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { Model } from 'mongoose';
import { Product, ProductDocument, Productschema } from '../schemas/products.schema';
import { ProductsService } from './products.service';

describe('ProductsService', () => {
  let service: ProductsService;
  let spyModel: Model<ProductDocument>;

  beforeEach(async () => {
    const productMockRepository = {
      find: () => {
        return {exec: jest.fn(() => {})};
      },
      findAll: () => {
        return {exec: jest.fn(() => {})};
      },
      create: jest.fn(() => {}),
      findByIdAndUpdate: () => {
        return {exec: jest.fn(() => {})};
      }
    };
  
    const module: TestingModule = await Test.createTestingModule({
      imports: [
      //   MongooseModule.forRoot(process.env.MONGODB_URL),
        // MongooseModule.forFeature([{ name: FraudRule.name, schema: Productschema }])
      ],
      providers: [
        ProductsService,
        {
          provide: getModelToken(Product.name),
          useValue: productMockRepository
        }
      ],
    }).compile();

    service = module.get<ProductsService>(ProductsService);
    spyModel = module.get<Model<ProductDocument>>(Model);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  it('should be call the create method in the model', () => {
    expect(service.create).toBeDefined();
  });
});

当我尝试运行代码时出现此错误

   Nest could not find Model element (this provider does not exist in the current context)

      38 |
      39 |     service = module.get<ProductsService>(ProductsService);
    > 40 |     spyModel = module.get<Model<ProductDocument>>(Model);

我不确定如何为此服务编写测试以及如何模拟 ProductModel。当我在没有模拟的情况下编写测试并直接写入数据库时​​,它可以工作,但我不能编写连接数据库的单元测试,因为它将是反模式,所以我必须模拟模型。

标签: javascriptnode.jsmongoosejestjsnestjs

解决方案


你已经非常接近答案了!在失败的get调用中,您需要使用getModelToken(Product.name)以便设置get以检索与模拟相同的注入令牌。

spyModel = module.get<Model<ProductDocument>>(getModelToken(Product.name));

推荐阅读