基于Node.js的Jest API测试失败问题求助
解决Jest+Supertest测试超时与进程无法退出的问题
1. 避免测试时自动启动Server
你的server.js中直接调用了start(),当测试文件导入app或server.js时,会自动启动真实Server并占用端口,导致Supertest请求卡住。修改server.js,仅在直接运行该文件时启动Server:
const server = http.createServer(app); const start = async () => { try { await connectDB(process.env.MONGO_URL) server.listen(port, () => console.log(`Server is listening on port ${port}...`) ); } catch (error) { console.error(error); // 添加错误日志,方便排查问题 } }; // 仅当直接运行server.js时启动服务 if (require.main === module) { start(); } // 导出app供测试使用 module.exports = { app };
2. 修复测试用例的请求逻辑
你的测试向/register发送POST请求时未携带任何参数,而实际接口大概率需要用户名、密码等必填字段,这会导致接口逻辑卡住或返回错误,进而触发超时。补充必要的请求参数:
const request = require('supertest') const { app } = require('../server'); // 导入正确的app实例 describe('Test POST /register', ()=>{ test('It should respond with 200 success', async ()=>{ const response = await request(app) .post('/register') .send({ username: 'test_jest_user', password: 'test_jest_pass123' }); // 根据接口实际要求传入字段 expect(response.statusCode).toBe(200); }, 10000); // 正常接口响应无需设置80000ms的超长超时 // 实现参数校验的测试用例 test('It should catch password must be present', async ()=>{ const response = await request(app) .post('/register') .send({ username: 'test_jest_user' }); // 故意不传密码 expect(response.statusCode).toBe(400); // 假设接口返回400表示参数缺失 // 可额外断言错误信息 expect(response.body.message).toBe('password must be present'); }); });
3. 测试后关闭数据库与Redis连接
测试结束后,MongoDB和Redis的连接未关闭会导致Jest进程无法退出。在测试文件中添加全局清理钩子:
// 导入你的数据库客户端实例(根据实际使用的库调整) const mongoose = require('mongoose'); const redisClient = require('../path-to-your-redis-client'); afterAll(async () => { // 关闭MongoDB连接 await mongoose.connection.close(); // 关闭Redis连接 await redisClient.quit(); });
4. 排查接口内部的异步阻塞
如果以上操作后仍超时,检查register接口的逻辑:
- 确认所有异步操作(Mongo写入、Redis存储)都正确使用
await,没有遗漏导致Promise未resolve - 检查是否有无限循环、等待外部资源的逻辑
- 在接口代码中添加日志,观察执行到哪一步卡住
最后,可通过--verbose参数查看测试详细执行过程:
npm test -- --verbose
内容的提问来源于stack exchange,提问作者user19263124
相关产品推荐
相关产品推荐

