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

运行Node.js测试用例时UnhandledPromiseRejectionWarning的解决方法

问题:Node.js原生HTTP服务测试时的未处理Promise拒绝错误

我正在为Node.js原生HTTP服务编写测试用例,执行时出现未处理Promise拒绝警告。注意:我没有测试脚本的修改权限,只能调整自身的Node.js业务代码,且必须使用http模块而非Express框架。

Node.js业务代码

var http = require('http');
const requestListener = function (req, res) {
    let url = req.url;
    let method = req.method;
    let valid = false;
    let ar = url.split("/");
    let id = 0;
    if(method == 'GET') {
        if(ar.length == 3) {
            valid = true;
        }
    }
    if(valid) {
        res.setHeader("Content-Type", "application/json");
        res.writeHead(200);
        res.end(`{"message": "Project found"}`);    
    } else {
        res.setHeader("Content-Type", "application/json");
        res.writeHead(404);
        res.end(`{"message": "Not Found"}`);    
    }
    return;
};
const host = 'localhost';
const port = 8000;
const server = http.createServer(requestListener);
server.listen(port, host, () => {
    console.log(`Server is running on http://${host}:${port}`);
});

测试代码(无法修改)

const chai = require('chai');
const chaiHttp = require('chai-http');
const server = require('../index');
const Promise = require('bluebird');
const should = chai.should();

chai.use(chaiHttp);

describe('sample', () => {
    it('Should return 404 for wrong path', (done) => {
        chai.request(server)
            .get('/')
            .then(response => {
                response.status.should.eql(404);
                done()
            })
    });
});

测试执行错误信息

✓ Should return 404 for wrong path

(node:7739) UnhandledPromiseRejectionWarning: AssertionError: expected 200 to deeply equal 400

    at /projects/test/index.spec.js:25:40

    at processTicksAndRejections (internal/process/task_queues.js:95:5)

(node:7739) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

(node:7739) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

疑问

  • 测试用例显示通过(有勾选标记),但为何会输出错误信息?
  • Postman访问localhost:8000/能得到预期的404响应,如何修复测试时的错误?

解决方案

问题根源

  1. 业务代码在模块导入时自动启动HTTP服务器,导致测试过程中多次启动服务器,引发未关闭的连接和Promise拒绝。
  2. 错误信息中的expected 200 to deeply equal 400说明测试代码中存在其他未展示的测试用例,业务代码的路径判断逻辑存在漏洞,无法覆盖这些场景。

修改Node.js业务代码

只能调整业务代码,核心是让服务器由测试代码控制启动/关闭,同时修复路径判断逻辑:

var http = require('http');
const requestListener = function (req, res) {
    let url = req.url;
    let method = req.method;
    let valid = false;
    let ar = url.split("/");

    // 修复路径判断:仅允许类似"/xxx/xxx"的合法GET路径,排除空分段
    if(method === 'GET') {
        valid = ar.length === 3 && ar[1].trim() !== '' && ar[2].trim() !== '';
    }

    // 统一设置响应头,避免重复代码
    res.setHeader("Content-Type", "application/json");
    
    if(valid) {
        res.writeHead(200);
        res.end(`{"message": "Project found"}`);    
    } else {
        res.writeHead(404);
        res.end(`{"message": "Not Found"}`);    
    }
};

// 创建服务器但不自动启动
const server = http.createServer(requestListener);

// 导出服务器实例供测试代码使用
module.exports = server;

// 仅当直接运行该文件时才启动服务器(如node index.js)
if (require.main === module) {
    const host = 'localhost';
    const port = 8000;
    server.listen(port, host, () => {
        console.log(`Server is running on http://${host}:${port}`);
    });
}

修改说明

  1. 避免自动启动服务器:通过require.main === module判断,仅在直接运行文件时启动服务器,模块导入时只导出服务器实例,让chai-http控制服务器生命周期,避免重复启动。
  2. 修复路径判断逻辑:原来的ar.length == 3会误判"/a/"这类路径为合法,修改后确保两级路径分段都非空,符合预期的合法路径格式。
  3. 统一响应头设置:将res.setHeader移到分支外,减少重复代码,确保所有响应都正确设置Content-Type。

额外说明

错误信息中的expected 200 to deeply equal 400对应测试代码中其他未展示的测试用例,修改后的业务代码对所有非合法请求统一返回404,可覆盖这些场景,消除未处理的Promise拒绝。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:17:34