Jest detects open handle with Express app

时间:2018-08-22 13:53:19

标签: javascript express jestjs

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

3 个答案:

答案 0 :(得分:6)

因此,我通过将所有应用程序逻辑抽象到一个app.js文件中来解决了这个问题:

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

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

module.exports = app

然后使用我所有的服务器逻辑创建一个server.js文件:

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

然后将app.js导入到您的测试文件中,如下所示:

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

像魅力一样工作!

答案 1 :(得分:0)

尝试一下:

beforeAll(async () => {
    // let's create a server to receive integration calls
    app = express();
    app.get('/', (req, res) => res.send('Hello World!'));

    await new Promise((resolve) => {
        app.listen(6666, () => {
            console.log('Example app listening on port 6666!');
            return resolve();
        });
    });
});

afterAll(() => { console.log('closing...'); app.close(); });

答案 2 :(得分:0)

我遇到了同样的问题,昨天我能够解决它。问题是调用app.listen()。您应该避免在app.js文件或Jest测试文件中调用app.listen。只需使用来自app.js的路由导出应用即可。然后,您可以使用supertest在测试中发出请求。

// in your app.js
const app = express();
// add routes and middleware
module.exports = app;

// in your test file
import app from './app.js';
import supertest from 'supertest';

describe('test block', () => {
  it('test route', async (done) => {
    const res = await supertest(app).get('/').expect(200);
    done();
  });
});