NestJS测试Spec无法解析UsersService的UserModel依赖,求解决方案
NestJS测试无法解析UsersService依赖:UserModel不可用
错误信息
Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument "UserModel" at index [0] is available in the RootTestModule context.
Potential solutions: - Is RootTestModule a valid NestJS module? - If "UserModel" is a provider, is it part of the current RootTestModule? - If "UserModel" is exported from a separate @Module, is that module imported within RootTestModule? @Module({ imports: [ /* the Module containing "UserModel" */ ] }) 6 | 7 | beforeEach(async () => { > 8 | const module: TestingModule = await Test.createTestingModule({ | ^ 9 | providers: [UsersService], 10 | }).compile(); 11 |
项目基于NestJS+MongoDB实现对象存储,根模块已正确配置Mongoose和UsersModule,AppController的/端点测试正常,但UsersService和UsersController的测试均触发上述错误。
相关代码示例
UsersService测试代码
import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; describe('UsersService', () => { let service: UsersService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [UsersService], }).compile(); service = module.get<UsersService>(UsersService); }); it('should be defined', () => { expect(service).toBeDefined(); }); });
UsersModule代码
import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; import { MongooseModule } from '@nestjs/mongoose'; import { User, UserSchema } from './schemas/user.schema'; @Module({ imports: [ MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]), ], controllers: [UsersController], providers: [UsersService], }) export class UsersModule {}
UsersService代码
import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { User } from './schemas/user.schema'; import { Model } from 'mongoose'; import { CreateUserDto } from './dto/create-user.dto'; @Injectable() export class UsersService { constructor(@InjectModel(User.name) private userModel: Model<User>) {} async create(createUserDto: CreateUserDto): Promise<User> { const user = new this.userModel(createUserDto); return user.save(); } async findById(id: string): Promise<User> { return this.userModel.findById(id).exec(); } }
UsersController代码
import { Body, Controller, Get, Param, Post } from '@nestjs/common'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { User } from './schemas/user.schema'; @Controller('users') export class UsersController { constructor(private usersService: UsersService) {} @Post() async create(@Body() createUserDto: CreateUserDto) { await this.usersService.create(createUserDto); } @Get(':id') async findById(@Param('id') id: string): Promise<User> { return this.usersService.findById(id); } }
解决方案
方案1:直接导入UsersModule(最简方式)
测试模块无需单独声明UsersService,直接导入UsersModule即可自动继承模块内所有依赖配置(包括UserModel):
import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; import { UsersModule } from './users.module'; describe('UsersService', () => { let service: UsersService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ imports: [UsersModule], // 替换原有的providers数组 }).compile(); service = module.get<UsersService>(UsersService); }); it('should be defined', () => { expect(service).toBeDefined(); }); });
方案2:手动模拟UserModel(单元测试隔离)
如果需要隔离数据库依赖,可手动模拟UserModel的实现,避免连接真实数据库:
import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; import { getModelToken } from '@nestjs/mongoose'; import { User } from './schemas/user.schema'; describe('UsersService', () => { let service: UsersService; let mockUserModel: any; beforeEach(async () => { // 模拟UserModel核心方法 mockUserModel = { findById: jest.fn().mockReturnThis(), exec: jest.fn(), save: jest.fn(), constructor: jest.fn().mockImplementation((dto) => ({ ...dto, save: mockUserModel.save })), }; const module: TestingModule = await Test.createTestingModule({ providers: [ UsersService, { provide: getModelToken(User.name), // 使用Nest提供的模型注入令牌 useValue: mockUserModel, // 注入模拟的模型对象 }, ], }).compile(); service = module.get<UsersService>(UsersService); }); it('should be defined', () => { expect(service).toBeDefined(); }); // 示例:测试create方法逻辑 it('should create a user', async () => { const createUserDto = { name: 'Test User', email: 'test@example.com' }; mockUserModel.save.mockResolvedValue(createUserDto); const result = await service.create(createUserDto); expect(result).toEqual(createUserDto); expect(mockUserModel.save).toHaveBeenCalled(); }); });
方案说明
- 方案1适合集成测试,复用现有模块配置,确保测试环境与生产环境依赖一致。
- 方案2适合单元测试,通过模拟模型隔离外部依赖,专注验证Service本身的业务逻辑。
内容的提问来源于stack exchange,提问作者kchak
相关产品推荐
相关产品推荐

