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

NestJS中TestingModule.get()获取的EntityManager未被Mock的原因及解决方法

问题解答

1. 行为差异的原因

这是因为NestJS的TypeORM模块对EntityManager和Repository的注入逻辑存在差异:

  • 对于通过getRepositoryToken(Entity, 'replica')注册的Repository,Nest会直接使用你提供的Mock实例,不会额外自动创建真实对象——因为Repository是绑定到特定实体和连接的具象化依赖,不存在自动实例化的兜底逻辑。
  • 对于EntityManager,TypeORM模块内部存在自动实例化逻辑:如果测试模块中存在TypeORM的连接配置(哪怕是隐式的,比如Service所在模块导入了TypeORMModule),Nest会优先从连接池中获取真实的EntityManager实例,直接覆盖你通过getEntityManagerToken('replica')注册的Mock,这就是你拿到全新未Mock实例的核心原因。

2. 可以通过moduleRef获取正确Mock的EntityManager

完全可以,只要调整测试模块的配置,阻断Nest自动创建真实EntityManager的逻辑即可。

3. 具体实现方案

核心是确保测试模块不引入真实的TypeORM连接配置,并明确覆盖EntityManager的注入逻辑。修正后的代码示例如下:

import { Test, TestingModule } from '@nestjs/testing';
import { getEntityManagerToken, getRepositoryToken } from '@nestjs/typeorm';
import { EntityManager, Inject } from 'typeorm';

const mockEntityManager = () => ({
  query: jest.fn(),
  find: jest.fn(),
  findOne: jest.fn(),
});

// 示例Service结构
class Service {
  constructor(
    @Inject(getEntityManagerToken('replica')) private readonly replicaManager: EntityManager,
    @Inject(getRepositoryToken(Entity, 'replica')) private readonly replicaRepo: any,
  ) {}
}

describe('TEST', () => {
  let sut: Service;
  let replicaRepositoryStub: any;
  let replicaManagerStub: any;

  beforeEach(async () => {
    // 提前创建Mock实例,便于后续统一引用
    const mockManager = mockEntityManager();
    const mockRepo = mockEntityManager();

    const moduleRef: TestingModule = await Test.createTestingModule({
      providers: [
        Service,
        {
          provide: getEntityManagerToken('replica'),
          useValue: mockManager,
        },
        {
          provide: getRepositoryToken(Entity, 'replica'),
          useValue: mockRepo,
        },
      ],
      // 关键:不要导入TypeORMModule.forRoot()或forFeature(),避免触发真实连接创建
    }).compile();

    sut = moduleRef.get<Service>(Service);
    replicaRepositoryStub = moduleRef.get(getRepositoryToken(Entity, 'replica'));
    replicaManagerStub = moduleRef.get(getEntityManagerToken('replica'));
  });

  it('test1', async () => {
    replicaRepositoryStub.findOne.mockResolvedValue('test'); 
    replicaManagerStub.findOne.mockResolvedValue('test'); 
    // 现在可正常执行,不会报错
  });
});

如果测试必须导入包含TypeORMModule的业务模块,可通过overrideProvider强制覆盖EntityManager的注入:

const moduleRef: TestingModule = await Test.createTestingModule({
  imports: [YourFeatureModule], // 该模块内部导入了TypeORMModule
  providers: [Service],
})
.overrideProvider(getEntityManagerToken('replica'))
.useValue(mockManager)
.compile();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:55:17