0

Step to reproduce

  1. Create a new nest project : nest new nest-app
  2. Install dependencies : npm i @nestjs/bullmq ioredis
  3. Start a redis instance on default port 6379
  4. Create this 2 files

app.service.ts

import { Injectable } from '@nestjs/common';
import { Job, Queue, Worker } from 'bullmq';
import Redis, { RedisOptions } from 'ioredis';

@Injectable()
export class AppService {
  private queue: Queue;
  private worker: Worker;
  private redis: Redis;

  connect() {
    const redisConfig: RedisOptions = {
      host: 'localhost',
      port: 6379,
      autoResubscribe: false,
      lazyConnect: true,
      maxRetriesPerRequest: 0,
      reconnectOnError: null,
      enableOfflineQueue: true,
    };
    this.redis = new Redis(redisConfig);
    this.queue = new Queue('queue1', { connection: this.redis });
    this.worker = new Worker(
      'queue1',
      async (job) => {
        console.log('PROCESS')
        await this.wait({});
        console.log('DONE')
        return job;
      },
      { connection: this.redis },
    );
    // Replace by this line and it works
    // this.worker = new Worker('queue1', '', { connection: this.redis });
  }

  async disconnect(): Promise<void> {
    await this.queue.close();
    await this.worker.close();
    await this.redis.quit();
  }

  async wait({ seconds = 1 }: { seconds?: number }): Promise<void> {
    await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
  }
}

app.service.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { AppService } from './app.service';

describe('Queue Service', () => {
  let appService: AppService;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [AppService],
    }).compile();
    appService = module.get<AppService>(AppService);
    appService.connect();
  });

  afterAll(async () => {
    await appService.disconnect();
  });

  it('Should pass', async () => {
    expect(true).toBeTruthy();
  });
});

Actual result

The test is still running with

Jest did not exit one second after the test run has completed.

'This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

Expected result

The test just succeed

Versions

node : 16.20.1

npm : 9.8.1

"dependencies": {
    "@nestjs/bullmq": "^10.0.1",
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "ioredis": "^5.3.2",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.8.1"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.0",
    "@nestjs/schematics": "^10.0.0",
    "@nestjs/testing": "^10.0.0",
    "@types/express": "^4.17.17",
    "@types/jest": "^29.5.2",
    "@types/node": "^20.3.1",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^5.59.11",
    "@typescript-eslint/parser": "^5.59.11",
    "eslint": "^8.42.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-plugin-prettier": "^4.2.1",
    "jest": "^29.5.0",
    "prettier": "^2.8.8",
    "source-map-support": "^0.5.21",
    "supertest": "^6.3.3",
    "ts-jest": "^29.1.0",
    "ts-loader": "^9.4.3",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.1.3"
  },
Yaroslavm
  • 1,762
  • 2
  • 7
  • 15
TheSmartMonkey
  • 857
  • 1
  • 7
  • 23

1 Answers1

0

It looks like Jest process was shutdown before disconnect() function promise was resolved.

Try

afterAll(async () => {
  await appService.disconnect();
});

Also add --detectOpenHandles to jest execution in package.json

Example:

"test:e2e": "jest --detectOpenHandles --config ./test/jest-e2e.json"

enter image description here

Yaroslavm
  • 1,762
  • 2
  • 7
  • 15