'Mocking Bull queues in NestJS

I am trying to test that after sending a request to one of my controllers, the queue pushes a job. Implementation itself works as expected.

This is my app.module.ts

    @Module({
    imports: [
    HttpModule,
    TypeOrmModule.forRoot(typeOrmConfig),
    BullModule.forRoot({
      redis: {
        host: redisConfig.host,
        port: redisConfig.port,
      },
    }),
    // Bunch of unrelated modules
     ],
     providers: [
    {
      provide: APP_FILTER,
      useClass: AllExceptionsFilter,
    },
    ],
     controllers: [SomeControllers],
    })
    export class AppModule {}

And this is how my import.module.ts (module using queues) looks like:

@Module({
  imports: [
    BullModule.registerQueue({
      name: importQueueName.value,
    }),
   //More unrelated modules,
  ],
  providers: [
    //More services, and bull consumer and producer,
    ImportDataProducer,
    ImportDataConsumer,
    ImportDataService,
  ],
  controllers: [ImportDataController],
})
export class ImportDataModule {}

So as I said functionally the implementation works good

I tried to follow this approach

Which does not register the queue in the beforeAll hook, and I'm getting

 Driver not Connected

And this approach

Which registers a queue in the beforeAll hook in the test suite, and I am getting:

 TypeError: Cannot read properties of undefined (reading 'call')

      at BullExplorer.handleProcessor (node_modules/@nestjs/bull/dist/bull.explorer.js:95:23)
      at MapIterator.iteratee (node_modules/@nestjs/bull/dist/bull.explorer.js:59:26)
      at MapIterator.next (node_modules/iterare/src/map.ts:9:39)
      at FilterIterator.next (node_modules/iterare/src/filter.ts:11:34)
      at IteratorWithOperators.next (node_modules/iterare/src/iterate.ts:19:28)
          at Function.from (<anonymous>)
      at IteratorWithOperators.toArray (node_modules/iterare/src/iterate.ts:227:22)
      at MetadataScanner.scanFromPrototype (node_modules/@nestjs/core/metadata-scanner.js:12:14)
      at node_modules/@nestjs/bull/dist/bull.explorer.js:56:34
          at Array.forEach (<anonymous>)

This is my 'base test suite':

describe('Queue test suite', () => {
  let app: INestApplication;
  const importQueue: any = { add: jest.fn() };
  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule, ImportDataModule],
    })
      .overrideProvider(importQueueName.value)
      .useValue(importQueue)
      .compile();

    app = moduleFixture.createNestApplication();
    app.useGlobalPipes(
      new ValidationPipe({
        transform: true,
        whitelist: true,
        forbidNonWhitelisted: true,
      }),
    );
    await app.init();
  });

  afterAll(async () => {
   
    await app.close();
 
  });

  test('A job should be pushed', async () => {
    await request(app.getHttpServer())
      .post('/some/route')
      .attach('file', __dirname + '/some.file')
      .expect(HttpStatus.CREATED);
   

    expect(importQueue.add).toHaveBeenCalled();
  });
});

Any idea on what could be wrong here? Thanks!



Solution 1:[1]

I had the same issue, the problem is with your mockQueue. You need to add a process mocked function.

This should work for you!

const importQueue: any = { 
  add: jest.fn(),
  process: jest.fn(),
};

And this is how I tested it.

expect(mockQueue.add).toBeCalledTimes(1);
      expect(mockQueue.add).nthCalledWith(
        1,
        PendoJobNames.SCR,
        {
          ...mockJobDto,
        },
        {
          jobId: mockDto.visitorId,
          removeOnComplete: true,
          removeOnFail: true,
        },
      );
    ```

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 moogs