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

如何在Jest中Mock NestJS的RabbitMQ模块?求解决方案

Mock @golevelup/nestjs-rabbitmq 解决连接失败问题

问题场景

现有AppModule代码如下:

import { Module } from '@nestjs/common'
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq'

@Module({
    imports: [
        RabbitMQModule.forRoot(RabbitMQModule, {
            exchanges: [
                {
                    name: 'my_rabbit',
                    type: 'direct',
                },
            ],
            uri: process.env.RABBITMQ_URI,
            connectionInitOptions: { wait: true },
        }),
    ],
})
export class AppModule {}

尝试两种Mock方式均失败:

方式一:覆盖AmqpConnection提供者

代码:

import { Module } from '@nestjs/common'
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq'

beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            imports: [
                AppModule
            ],
        })
            .overrideProvider(AmqpConnection)
            .useValue(createMock<AmqpConnection>())
            .compile()
    })

报错:

[Nest] 2745  - 24/07/2022, 17:02:54   ERROR [AmqpConnection] Disconnected from RabbitMQ broker (default)
Error: connect ECONNREFUSED 127.0.0.1:5672

原因:RabbitMQModule.forRoot在模块初始化阶段就会尝试建立真实连接,overrideProvider的操作时机太晚,无法阻止连接请求。

方式二:直接Mock整个模块

代码:

jest.mock('@golevelup/nestjs-rabbitmq')

报错:

Nest cannot create the AppModule instance.
    The module at index [0] of the AppModule "imports" array is undefined.

原因:jest.mock会把模块的所有导出替换为undefined,导致RabbitMQModule.forRoot无法返回有效模块实例。

正确解决方案

方案1:Mock RabbitMQModule的forRoot方法

通过jest.mock自定义模块导出,让forRoot返回空Nest模块,同时MockAmqpConnection类:

import { Test } from '@nestjs/testing';
import { AppModule } from './app.module';
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
import { createMock } from '@golevelup/ts-jest';

jest.mock('@golevelup/nestjs-rabbitmq', () => ({
  RabbitMQModule: {
    forRoot: jest.fn().mockReturnValue({
      module: class {},
    }),
  },
  AmqpConnection: jest.fn(),
}));

describe('AppModule', () => {
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    })
      .overrideProvider(AmqpConnection)
      .useValue(createMock<AmqpConnection>())
      .compile();
  });

  // 测试用例编写...
});

方案2:手动构建测试依赖,避免真实连接

直接在测试模块中导入业务模块,配合Mock配置的RabbitMQModule,跳过真实连接逻辑:

import { Test } from '@nestjs/testing';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { createMock } from '@golevelup/ts-jest';
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
import { YourService } from './your.service';

describe('YourService', () => {
  let service: YourService;
  let amqpConnection: jest.Mocked<AmqpConnection>;

  beforeEach(async () => {
    amqpConnection = createMock<AmqpConnection>();

    const module: TestingModule = await Test.createTestingModule({
      imports: [
        RabbitMQModule.forRoot(RabbitMQModule, {
          exchanges: [{ name: 'my_rabbit', type: 'direct' }],
          uri: 'amqp://guest:guest@localhost:5672',
          connectionInitOptions: { wait: false }, // 禁用连接等待
        }),
      ],
      providers: [YourService],
    })
      .overrideProvider(AmqpConnection)
      .useValue(amqpConnection)
      .compile();

    service = module.get<YourService>(YourService);
  });

  it('should trigger RabbitMQ publish', () => {
    service.sendTestMessage();
    expect(amqpConnection.publish).toHaveBeenCalled();
  });
});

方案3:用overrideModule替换原RabbitMQModule

若要保留AppModule结构,可通过overrideModule替换掉原有的RabbitMQModule导入:

import { Test } from '@nestjs/testing';
import { AppModule } from './app.module';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { createMock } from '@golevelup/ts-jest';
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';

describe('AppModule', () => {
  beforeEach(async () => {
    const mockRabbitModule = RabbitMQModule.forRoot(RabbitMQModule, {
      exchanges: [{ name: 'my_rabbit', type: 'direct' }],
      uri: 'amqp://mock:mock@localhost:5672',
      connectionInitOptions: { wait: false },
    });

    const module: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    })
      .overrideModule(RabbitMQModule)
      .useModule(mockRabbitModule)
      .overrideProvider(AmqpConnection)
      .useValue(createMock<AmqpConnection>())
      .compile();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:18:18