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

使用Chai和Mocha测试RESTful API时遇端口占用错误求助

解决Chai+Mocha测试API时的EADDRINUSE错误

错误原因

  1. 你每个测试用例(it)都调用了startServer,而app.listen()每次执行都会尝试绑定5000端口。第一个测试启动服务器后,端口被占用,第二个测试再调用时就会抛出EADDRINUSE错误。
  2. 测试里的done()调用时机错误,放在了end()回调外面,会导致测试提前结束,断言逻辑可能没执行就标记测试完成。

修复方案

1. 统一管理服务器生命周期(核心修复)

只在所有测试前启动一次服务器,测试结束后关闭,避免重复占用端口:

修改server.ts:

让startServer返回服务器实例,方便后续关闭

import express, { Application } from "express";
import personRouter from "./route/person.route";
import groupRouter from "./route/group.route";
import bodyParser from "body-parser";

const app: Application = express();
// 测试环境用随机端口,避免冲突
const PORT: Number | string = process.env.NODE_ENV === 'test' ? 0 : 5000;

app.use(bodyParser.json());

app.use('/person', personRouter)
app.use('/group', groupRouter)

export function startServer() {
    // 返回server实例
    return app.listen(PORT, () => {
        const actualPort = (app.listen().address() as any).port;
        console.log(`Server started on http://localhost:${actualPort}`);
    });
}

修改test.ts:

用before/after钩子管理服务器启动和关闭,调整done()位置

chai.use(chaiHttp)
let server: any;

describe('Persons', () => {
  // 所有测试前启动一次服务器
  before(() => {
    server = startServer();
  });

  // 所有测试结束后关闭服务器
  after((done) => {
    server.close(done);
  });

  describe('GET /person/', () => {
    it('check error path', (done) => {
      chai
        .request(server) // 直接传入server实例,而非startServer函数
        .get("/person/") // 注意路径和server里注册的路由匹配(你之前写的是/persons/,这里要对应)
        .end((err, res) => {
          res.should.have.status(422);
          done(); // 放在回调内,确保断言执行完再结束测试
        });
    });
  });

  it('It should get person by first name', (done) => {
    chai
      .request(server)
      .get("/person/Ross") // 修正路径匹配server路由
      .end((err, res) => {
        res.should.have.status(200);
        res.body.should.be.a('string');
        done();
      });
  });
});

2. 额外注意事项

  • 测试路径要和server.ts里注册的路由严格匹配:你服务器里注册的是/person前缀,测试里不要写成/persons/,否则会触发404或自定义的错误状态码。
  • 如果本地有其他服务占用5000端口,也会导致同样错误,可以用lsof -i :5000(Mac/Linux)或netstat -ano | findstr :5000(Windows)找到占用进程并关闭。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:31:05