Supertest报TypeError:无法读取undefined的close属性问题求助
Express集成测试Supertest报错:TypeError: Cannot read properties of undefined (reading 'close')
核心原因
报错本质是两个可能的问题:要么你的src/index.js没有正确导出带有close()方法的HTTP Server实例,要么测试代码中存在模块缓存或异步处理不当,导致afterEach执行时server变量变为undefined。
解决方案
方案1:确保正确导出Server实例
Express的app对象本身没有close()方法,只有app.listen()返回的HTTP Server实例具备该方法。检查并修改你的src/index.js:
// src/index.js const express = require('express'); const app = express(); // 配置路由、中间件等逻辑... // 启动服务器并导出Server实例 const server = app.listen(process.env.PORT || 3000, () => { console.log('Server running on port:', process.env.PORT || 3000); }); module.exports = server;
方案2:修复测试中的异步与变量检查问题
server.close()是异步操作,直接调用可能导致测试未等待关闭完成就结束,同时添加存在性判断避免server为undefined:
const request = require('supertest'); let server; beforeEach(() => { server = require('../../../src/index'); }); // 用Promise等待close完成,并添加存在性判断 afterEach(async () => { if (server) { await new Promise(resolve => server.close(resolve)); server = undefined; // 重置变量,避免影响后续测试 } }); describe('POST', () => { it('should check if user sent required parameters', async () => { const res = await request(server).post('/users'); expect(res.status).toBe(400); }); });
方案3:拆分App与Server创建(推荐)
将Express app的定义与服务器启动分离,避免Node.js模块缓存导致的重复启动问题:
// src/app.js const express = require('express'); const app = express(); // 配置路由、中间件等逻辑... module.exports = app;
// src/index.js const app = require('./app'); const server = app.listen(process.env.PORT || 3000); module.exports = server;
测试代码改为每次启动新的Server实例:
const request = require('supertest'); const app = require('../../../src/app'); let server; beforeEach(() => { // 用0让系统分配随机端口,避免端口占用冲突 server = app.listen(0); }); afterEach(async () => { await new Promise(resolve => server.close(resolve)); }); describe('POST', () => { it('should check if user sent required parameters', async () => { const res = await request(server).post('/users'); expect(res.status).toBe(400); }); });
关键说明
- 不要混淆Express的
app对象与app.listen()返回的Server实例,只有后者具备close()方法。 - Node.js会缓存require的模块,多次require同一文件只会执行一次模块代码,直接在模块中启动服务器容易导致测试间的状态污染。
- 异步操作(如
server.close())必须等待完成,否则会导致测试资源未正确释放,影响后续用例。
内容的提问来源于stack exchange,提问作者Rahimi0151
相关产品推荐
相关产品推荐

