Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest detects open handle with Express app

I've been trying to figure this out for a while now, but with no luck. I initially had the issue when performing simple integration tests with a MongoDB database, but I've stripped the code right down and made it as simple as I can. The only thing I have running is a single test file:

// blah.test.js
const express = require('express');
const app = express();

describe('test block', () => {
    let server = null;

    beforeEach(() => {
        server = app.listen(3000, () => console.log('Listening on port 3000'));
    });

    afterEach(async () => {
        await server.close();
    });

    it('should pass the test', () => {
        expect(1).toBe(1);
    });
});

The test passes, but Jest informs me of an open handle which could prevent it from exiting:

enter image description here

On this occasion, it did exit, but still notices an open handle. I would like to know how to safely close this, without forcing exit. With previous tests, I would get the same open handle warning, but also with an error stating that Jest didn't exit one second after completing the tests.

I also tried using beforeAll() and afterAll(), instead of beforeEach() and afterEach(), but still get the same problem. I know the test doesn't require the server on this occasion, but I was trying to make it as simple as possible to try to find the issue with opening and closing the server.

UPDATE: I noticed that it seems to work fine as soon as I add a second test file:

// blah2.test.js
const express = require('express');
const app = express();

describe('test block', () => {
    let server = null;

    beforeEach(() => {
        server = app.listen(3000, () => console.log('Listening on port 3000'));
    });

    afterEach(async () => {
        await server.close();
    });

    it('should pass the test', () => {
        expect(2).toBe(2);
    });
});

No open handles with two tests running

If anyone can share any ideas as to why this happens, it would be much appreciated.

I am using:

Express: 4.16.3

Jest: 23.5.0

NPM: 6.3.0

like image 698
H. Majury Avatar asked Aug 22 '18 13:08

H. Majury


People also ask

What is Jsdom Jest?

jsdom is a pure JavaScript implementation of the DOM and browser APIs that runs in node. If you're not using Jest and you would like to run your tests in Node, then you must install jsdom yourself. There's also a package called global-jsdom which can be used to setup the global environment to simulate the browser APIs.

What is Jest Nodejs?

Jest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!

How do you find open handles in Jest?

Try running with --runInBand --detectOpenHandles to find leaks. Jest did not exit one second after the test run has completed.

Does Jest have Jsdom?

Jest actually ships with jsdom and the environment already configured. You can override it with the testEnvironment setting. If you need to set up more aspects of the environment though, you can use the setupTestFrameworkScriptFile setting to point to a file that executes before all of your tests run.


1 Answers

So I solved the issue by abstracting all the app logic to an app.js file:

const express = require('express');
const routes = require('./routes');
const app = express();

app.use('/api', routes);

module.exports = app

Then creating a server.js file with all my server logic:

const app = require('./app.js')
const PORT = process.env.PORT || 3000
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`))

Then just import app.js into your test file like this:

const app = require('../app.js')

Works like a charm!

like image 143
Bruno Avatar answered Oct 05 '22 23:10

Bruno