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

如何在Nest.js与Jest单元测试中Stub Entity Manager解决连接未找到错误

TypeORM 单元测试Stub EntityManager解决方案

报错原因

你遇到的连接未找到报错,本质是Stub getManager 时没有完整模拟其返回结构,或是Stub时机不正确,导致代码执行时仍然调用了TypeORM原生的getManager逻辑,尝试建立真实数据库连接。

方案1:全局Stub getManager 方法(无需修改现有业务代码)

以下以Jest测试框架为例,其他框架(如Mocha+Sinon)逻辑一致:

// 首先全局mock typeorm的getManager导出
jest.mock('typeorm', () => ({
  ...jest.requireActual('typeorm'),
  getManager: jest.fn()
}))

it('createStore 方法应正常创建服务实体', async () => {
  // 1. 构造测试入参和预期返回值
  const mockDto = { serviceName: '测试服务' } as ServiceCreateDto
  const mockEntity = { id: 1001, ...mockDto } as ServiceEntity

  // 2. 模拟事务实例,实现用到的create、save方法
  const mockTransaction = {
    create: jest.fn().mockReturnValue(mockEntity),
    save: jest.fn().mockResolvedValue(mockEntity)
  }

  // 3. 模拟EntityManager实例,实现用到的transaction方法
  const mockManager = {
    transaction: jest.fn().mockImplementation(async (transactionCallback) => {
      // 执行传入的事务回调,把模拟的事务实例传进去
      await transactionCallback(mockTransaction)
    })
  }

  // 4. 给getManager打桩,返回模拟的EntityManager实例
  (getManager as jest.Mock).mockReturnValue(mockManager)

  // 5. 调用待测方法
  const result = await yourServiceInstance.createStore(mockDto)

  // 6. 断言验证逻辑正确性
  expect(getManager).toHaveBeenCalled()
  expect(mockTransaction.create).toHaveBeenCalledWith(ServiceEntity, mockDto)
  expect(mockTransaction.save).toHaveBeenCalledWith(mockEntity)
  expect(result).toEqual(mockEntity)
})

方案2:依赖注入重构(长期项目更推荐)

直接在业务代码中调用全局getManager会导致代码耦合度高,测试不够灵活,建议通过依赖注入的方式传入EntityManager实例:

修改后业务代码

import { EntityManager } from 'typeorm'
import { InjectEntityManager } from '@nestjs/typeorm' // 如果用Nest框架的话,否则自行实现注入

class YourService {
  constructor(
    // 注入EntityManager实例,不要在方法内部调用getManager
    @InjectEntityManager()
    private readonly entityManager: EntityManager,
    private readonly logger: Logger
  ) {}

  async createStore(dto: ServiceCreateDto): Promise<ServiceDto> {
    let entity: ServiceEntity;
    try {
      await this.entityManager.transaction(async transaction => {
        entity = transaction.create(ServiceEntity, dto)
        await transaction.save(entity);
        this.logger.log(`created new Service with serviceId: ${entity.id}`);
      });
      return entity;
    } catch (error) {
        throw error;
    }
  }
}

对应测试代码

不需要全局mock TypeORM,直接构造模拟实例传入构造函数即可:

it('createStore 方法应正常创建服务实体', async () => {
  const mockDto = { serviceName: '测试服务' } as ServiceCreateDto
  const mockEntity = { id: 1001, ...mockDto } as ServiceEntity

  const mockTransaction = {
    create: jest.fn().mockReturnValue(mockEntity),
    save: jest.fn().mockResolvedValue(mockEntity)
  }
  const mockEntityManager = {
    transaction: jest.fn().mockImplementation(cb => cb(mockTransaction))
  }
  const mockLogger = { log: jest.fn() }

  // 直接把模拟的EntityManager传入构造函数
  const service = new YourService(mockEntityManager as unknown as EntityManager, mockLogger)

  const result = await service.createStore(mockDto)
  expect(mockEntityManager.transaction).toHaveBeenCalled()
  expect(result).toEqual(mockEntity)
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:45:03