You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Express与Supertest测试中的TCPWRAP/TCPSERVERWRAP问题

解决Jest测试Express应用时的TCPWRAP与TCPSERVERWRAP未关闭句柄问题

使用Supertest测试Express应用时,Jest会检测到两个未关闭的句柄导致无法正常退出:

  • TCPWRAP:来自Mongoose的MongoDB连接未关闭
  • TCPSERVERWRAP:来自Express服务器的监听端口未释放

以下是针对性的解决方法:


1. 修复TCPSERVERWRAP问题(Express服务器残留)

问题根源是测试时直接引入了启动服务器的文件,app.listen()会持续占用端口,导致句柄无法释放。

解决步骤:

  • 拆分服务器启动逻辑,将app实例与启动代码分离
  • 测试文件只引入app实例,由Supertest自动管理服务器启停

代码改造:

  1. 修改主文件(如index.js),仅导出app实例:
// index.js
const express = require('express');
const app = express();

// 配置中间件、路由等逻辑...

// 移除直接调用的app.listen,改为导出app
module.exports = app;
  1. 创建独立的启动文件(如start.js):
// start.js
const app = require('./index');
const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Listening on port, ${PORT}`);
});
  1. 测试文件中引入app实例而非启动文件:
// test/integration/order.route.test.js
const request = require('supertest');
const app = require('../../index');

describe('Order Routes', () => {
  // 编写测试用例...
});

2. 修复TCPWRAP问题(Mongoose连接残留)

问题根源是测试结束后MongoDB连接未关闭,导致连接句柄残留。

解决步骤:

在测试套件的afterAll钩子中手动关闭Mongoose连接,确保测试完成后释放资源。

代码示例:

// test/integration/order.route.test.js
const request = require('supertest');
const app = require('../../index');
const mongoose = require('mongoose');

describe('Order Routes', () => {
  // 测试用例...

  afterAll(async () => {
    // 测试全部完成后关闭MongoDB连接
    await mongoose.connection.close();
  });
});

如果有多个测试文件,也可以通过Jest全局配置统一处理:

  1. 创建jest.config.js:
module.exports = {
  // 其他Jest配置...
  globalTeardown: './tests/teardown.js'
};
  1. 创建全局清理文件tests/teardown.js:
// tests/teardown.js
const mongoose = require('mongoose');

module.exports = async () => {
  await mongoose.connection.close();
};

内容的提问来源于stack exchange,提问作者Emmanuel Oloyede

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:00:59