skip to Main Content

I’m trying to setup E2E tests in a NestJS project, however, jest output looks like this:

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

After a lot of reading this is because there are some resources, not yet liberated, after some debugging it turns there’s an open connection to redis created by ioredis which is used by bull which is used by NestJS to do task queue processing. The thing is that I don’t have a reference to the connection in the test code, so how can I close it? I’m tearing down the Nest application in the afterAll jest’s hook like this:

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

but it does nothing, the connection is still there and the jest error message persists. I know I can just add the --forceExit to the jest command but that is not solving anything, it’s just hiding the problem under the rug.

3

Answers


  1. This took me awhile to figure out. You need to close the module in the afterAll hook. I was able to find this from looking at the tests in the nestJS Bull repo.

    describe('RedisTest', () => {
      let module: TestingModule;
      beforeAll(async () => {
    
        module = Test.createTestingModule({
          imports: [
            BullModule.registerQueueAsync({
              name: 'test2',
            }),
          ],
    
        });
      });
    
      afterAll(async () => {
        await module.close();
      });
    });
    

    https://github.com/nestjs/bull/blob/master/e2e/module.e2e-spec.ts

    Login or Signup to reply.
  2. After struggling almost to getting depressed i found a solution that worked for me.

    I’m using "@nestjs/bull": "^0.3.1", "bull": "^3.21.1".

    because the queue from bull package uses redis, it keeps the connection open although the module & app are closed.

        await moduleRef.close();
        await app.close();
    

    i realized that when using --detectOpenHandles while relying on leaked-handles library for more information, you will see something like this in the console:

        tcp stream {
           fd: 20,
           readable: true,
           writable: false,
           address: {},
           serverAddr: null
        }
    
        tcp handle leaked at one of: 
        at /media/user/somePartitionName/Workspace/Nest/project- 
        name/node_modules/ioredis/built/connectors/StandaloneConnector.js:58:45
        tcp stream {
           fd: 22,
           readable: true,
           writable: true,
           address: { address: '127.0.0.1', family: 'IPv4', port: 34876 },
           serverAddr: null
        }
    
    

    Solution
    using beforEach() & afterEach()

    • in beforEach(), add this instruction to get an instance of your queue :
        queue = moduleRef.get(getQueueToken("queuename"));
    
    • in afterEach(), close the queue like so: (also close your app & module for better practice)
        await queue.close();
    

    Note

    using beforAll() & afterAll() doesn’t work and the same problem occurs, at least from what i have tried, both beforEach() & afterEach() work combined.

    Login or Signup to reply.
  3. You don’t have to add queue.close() to every test, just close queues in their own service/provider using OnModuleDestroy Hook:

    @Injectable()
    export class ServicesConsumer implements OnModuleDestroy {
      constructor(
        @InjectQueue('services')
        private readonly servicesQueue: Queue,
      ) { }
    
      async onModuleDestroy() {
        await this.servicesQueue.close();
      }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search