Jest使用Express应用程序检测打开的句柄

H. *_*ury 8 javascript express jestjs

我一直试图解决这个问题,但没有运气.在使用MongoDB数据库执行简单的集成测试时,我最初遇到了这个问题,但是我已经将代码剥离下来,并尽可能地简化了代码.我唯一运行的是一个测试文件:

// 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);
    });
});
Run Code Online (Sandbox Code Playgroud)

测试通过了,但是Jest告诉我一个打开的手柄可能会阻止它退出:

在此输入图像描述

在这种情况下,它确实退出了,但仍然注意到一个打开的句柄.我想知道如何安全地关闭它,而不是强迫退出.通过以前的测试,我会得到相同的打开句柄警告,但也会出现错误,指出Jest在完成测试后没有退出一秒钟.

我使用也试过beforeAll()afterAll(),而不是beforeEach()afterEach(),但仍然得到了同样的问题.我知道测试在这种情况下不需要服务器,但我试图尽可能简单地尝试找到打开和关闭服务器的问题.

更新:我注意到,只要添加第二个测试文件,它似乎工作正常:

// 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);
    });
});
Run Code Online (Sandbox Code Playgroud)

没有运行两个测试的打开句柄

如果有人可以分享关于为什么会发生这种情况的任何想法,那将非常感激.

我在用:

快递:4.16.3

开玩笑:23.5.0

NPM:6.3.0

Bru*_*uno 12

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

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

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

module.exports = app
Run Code Online (Sandbox Code Playgroud)

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

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

然后app.js像这样导入到您的测试文件中:

const app = require('../app.js')
Run Code Online (Sandbox Code Playgroud)

奇迹般有效!


jjg*_*jgg 5

我有同样的问题,我昨天能够解决它。问题是调用 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();
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 测试函数不能同时接受“完成”回调并返回某些内容。要么使用“完成”回调,要么返回一个承诺。返回值:Promise{} (3认同)

Chr*_*ris 1

尝试这个:

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(); });
Run Code Online (Sandbox Code Playgroud)