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

测试集成MongoDB与Neo4J的NestJS服务时Jest报inspectModules未定义错误

解决Jest测试NestJS服务时的"TypeError: Cannot read properties of undefined (reading 'inspectModules')"错误

问题场景

我有一个同时操作MongoDB和Neo4J的UserService,其create方法会依次调用createUserInMongoDB和createUserInNeo4j方法,具体代码如下:

export class UserService {
  constructor(
    @InjectModel('User') private readonly userModel: Model<UserDocument>,
    @InjectModel('SportEvent')
    private readonly sportEventModel: Model<SportEventDocument>,
    private readonly neo4jQueryService: Neo4jQueryService
  ) {}

  //creating a user.
  async create(user: User): Promise<object> {
    let userInMongoDB: { mongoId: string; firstName: string };
    try {
      userInMongoDB = await this.createUserInMongoDB(user);
      const userIncreaeNeo4j = await this.createUserInNeo4j(
        userInMongoDB.firstName,
        userInMongoDB.mongoId
      );
      if (userIncreaeNeo4j && userInMongoDB) {
        return {
          statusCode: 201,
          message: `User succesfully created`,
        };
      }
    } catch (error) {
      if (userInMongoDB) {
        await this.userModel.findByIdAndDelete(userInMongoDB.mongoId).lean();
      }
      throw new HttpException(error.message, 400);
    }
  }

  //create user in mongoDB
  async createUserInMongoDB(
    user: User
  ): Promise<{ mongoId: string; firstName: string }> {
    try {
      const createdUser = new this.userModel(user);
      createdUser.email = user.email.toLowerCase();
      createdUser.firstName = user.firstName.toLowerCase();
      createdUser.lastName = user.lastName.toLowerCase();

      console.log(user);

      await createdUser.save();
      const userInMongoDB = {
        mongoId: createdUser._id.toString(),
        firstName: createdUser.firstName,
      };
      return userInMongoDB;
    } catch (error) {
      if (error.code === 11000) {
        throw new HttpException(
          'Duplicate entry, email has to be unique.',
          409
        );
      } else {
        throw new HttpException(error.message, 400);
      }
    }
  }

  //create user in neo4j
  async createUserInNeo4j(userName: string, userId: string): Promise<boolean> {
    try {
      await this.neo4jQueryService.write(
        `CREATE (n:User {mongoId: \"${userId}\", name: \"${userName}\"}) RETURN n`
      );
      return true;
    } catch (error) {
      throw new HttpException(error.message, 400);
    }
  }
}

我编写了一个简单的Jest测试用例,仅验证userService是否已定义,测试代码如下:

import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { UserService } from '../user.service';
import { Neo4jQueryService } from '../../../neo4-j/neo4-j.service';
import { UserDocument } from '../../Schemas/user.schema';
import { User } from '@sport-activity-app/domain';
import { HttpException } from '@nestjs/common';

describe('UserService', () => {
  let userService: UserService;
  let userModel: Model<UserDocument>;
  let neo4jQueryService: Neo4jQueryService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserService,
        Neo4jQueryService,
        {
          provide: getModelToken('User'),
          useValue: {
            // mock Mongoose Model methods used in the UserService class
            findByIdAndDelete: jest.fn(),
            create: jest.fn(),
          },
        },
        {
          provide: getModelToken('SportEvent'),
          useValue: {
            // mock Mongoose Model methods used in the UserService class
          },
        },
      ],
    }).compile();

    userService = module.get<UserService>(UserService);
    userModel = module.get<Model<UserDocument>>(getModelToken('User'));
    neo4jQueryService = module.get<Neo4jQueryService>(Neo4jQueryService);
  });

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

但运行测试时抛出错误:TypeError: Cannot read properties of undefined (reading 'inspectModules')


解决方案

错误原因

测试用例中直接注册了真实的Neo4jQueryService,而该服务在测试环境中可能依赖未初始化的Neo4j驱动、配置项或其他外部资源,导致实例化失败,进而触发inspectModules相关的未定义错误。

修复步骤

将真实的Neo4jQueryService替换为Mock实现,只模拟UserService中用到的write方法即可:

  • 在测试模块的providers数组中,替换Neo4jQueryService为Mock对象
  • 确保Mock对象包含write方法(用jest.fn()模拟)

修改后的完整测试代码

import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { UserService } from '../user.service';
import { Neo4jQueryService } from '../../../neo4-j/neo4-j.service';
import { UserDocument } from '../../Schemas/user.schema';
import { User } from '@sport-activity-app/domain';
import { HttpException } from '@nestjs/common';

describe('UserService', () => {
  let userService: UserService;
  let userModel: Model<UserDocument>;
  let neo4jQueryService: jest.Mocked<Neo4jQueryService>;

  beforeEach(async () => {
    // 创建Neo4jQueryService的Mock实现
    const mockNeo4jQueryService = {
      write: jest.fn().mockResolvedValue(true),
    } as jest.Mocked<Neo4jQueryService>;

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserService,
        // 注册Mock服务,替换真实的Neo4jQueryService
        {
          provide: Neo4jQueryService,
          useValue: mockNeo4jQueryService,
        },
        {
          provide: getModelToken('User'),
          useValue: {
            findByIdAndDelete: jest.fn().mockResolvedValue(true),
            // 模拟构造函数和save方法,适配createUserInMongoDB的调用
            constructor: jest.fn().mockImplementation((user) => ({
              ...user,
              email: user.email.toLowerCase(),
              firstName: user.firstName.toLowerCase(),
              lastName: user.lastName.toLowerCase(),
              save: jest.fn().mockResolvedValue({
                _id: 'mock-mongo-id',
                firstName: user.firstName.toLowerCase(),
              }),
            })),
          },
        },
        {
          provide: getModelToken('SportEvent'),
          useValue: {},
        },
      ],
    }).compile();

    userService = module.get<UserService>(UserService);
    userModel = module.get<Model<UserDocument>>(getModelToken('User'));
    neo4jQueryService = module.get(Neo4jQueryService);
  });

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

额外注意点

  • 若Neo4jQueryService使用自定义注入token(如@Inject('NEO4J_SERVICE')),需将Mock的provide值改为对应的token字符串
  • 补充了userModel的构造函数和save方法Mock,避免后续测试create方法时因调用真实Mongoose逻辑报错
  • 所有外部依赖都应使用Mock替代,确保测试不依赖真实服务或数据库

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 20:39:58