You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS单元测试user.module.ts时如何传递MongoDB依赖

报错含义

这个报错本质是Nest测试容器在解析依赖时,找不到MongooseModule.forFeature()注册User模型所依赖的全局数据库连接实例DatabaseConnection。
正常业务代码里,你会在根模块AppModule里导入MongooseModule.forRoot()初始化数据库连接,这个连接会作为全局Provider注入到所有子模块的Mongoose上下文里。但你写单元测试时只单独导入了UserModule,测试容器里根本没有初始化过Mongoose根连接,UserModel拿不到需要的连接参数,自然就抛了依赖解析失败的错误。

你的判断是否准确

你的方向是对的,但表述不完全准确:你不需要单独注入Mongoose Model本身,而是要给测试环境补全Mongoose运行依赖的根数据库连接,或者直接Mock掉所有和真实数据库相关的依赖——毕竟模块编译的单元测试不需要真的连业务数据库。

具体解决方法

根据你的测试目的选对应方案即可:

方案1:用内存Mongo跑近真实的集成测试

如果你的测试后续还要验证数据库相关逻辑,用内存Mongo是最省事的方案,不需要改业务代码:

  • 先安装mongodb-memory-server依赖
  • 在测试初始化时先启动内存Mongo实例,再把Mongoose根模块导入测试容器,连接内存库地址,最后再导入你的UserModule
    参考代码:
import { Test } from '@nestjs/testing';
import { UserModule } from './user.module';
import { MongooseModule } from '@nestjs/mongoose';
import { MongoMemoryServer } from 'mongodb-memory-server';

// 原测试里写的ThingsModule是笔误,直接改成对应模块名
describe('UserModule', () => {
  let mongod: MongoMemoryServer;

  beforeAll(async () => {
    mongod = await MongoMemoryServer.create();
  });

  afterAll(async () => {
    await mongod.stop();
  });

  it('should compile the module', async () => {
    const module = await Test.createTestingModule({
      imports: [
        // 先初始化Mongoose根连接,指向内存库
        MongooseModule.forRoot(mongod.getUri()),
        UserModule
      ],
    }).compile();

    expect(module).toBeDefined();
  });
});

方案2:Mock依赖跑纯单元测试(推荐,速度最快)

如果你只是为了覆盖user.module.ts的测试覆盖率,不需要验证数据库逻辑,直接Mock掉所有外部依赖就行,测试跑起来速度极快,也不需要额外装数据库相关的包:

import { Test } from '@nestjs/testing';
import { UserModule } from './user.module';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { HttpModule } from '@nestjs/axios';
import { Eauth } from './middlewares/eauth.middlewares';

describe('UserModule', () => {
  it('should compile the module', async () => {
    const module = await Test.createTestingModule({
      imports: [HttpModule],
      controllers: [UserController],
      providers: [
        UserService,
        // Mock Mongoose注入的UserModel
        {
          provide: 'UserModel',
          useValue: {
            find: jest.fn(),
            create: jest.fn(),
            findById: jest.fn(),
            updateOne: jest.fn(),
            deleteOne: jest.fn()
          }
        },
        // Mock自定义中间件
        {
          provide: Eauth,
          useValue: {
            use: jest.fn()
          }
        }
      ]
    }).compile();

    expect(module).toBeDefined();
  });

  // 顺便覆盖configure中间件注册的逻辑,把覆盖率拉满
  it('should register Eauth middleware for UserController', async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [UserModule]
    })
    .overrideProvider('DatabaseConnection')
    .useValue({})
    .overrideProvider('UserModel')
    .useValue({})
    .compile();

    const app = moduleRef.createNestApplication();
    const applyMock = jest.fn().mockReturnThis();
    const forRoutesMock = jest.fn();
    const mockConsumer = {
      apply: applyMock.mockImplementation(() => ({
        forRoutes: forRoutesMock
      }))
    };

    const userModule = app.get(UserModule);
    userModule.configure(mockConsumer as any);

    expect(applyMock).toHaveBeenCalledWith(Eauth);
    expect(forRoutesMock).toHaveBeenCalledWith(UserController);
  });
});

额外提示:你原测试文件里describe的名称写的是ThingsModule,属于复制代码留下的笔误,记得改成UserModule避免后续看测试报告混淆。

内容的提问来源于stack exchange,提问作者DavSev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:00:51