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

使用Express、Jest和Supertest时随机Axios错误的排查求助

问题:Supertest全量测试随机出现无堆栈的AxiosError 404错误
  • 单个测试文件单独运行全部通过,但全量运行40个文件共280个测试时,总会出现至少一次AxiosError: Request failed with status code 404错误,有时会出现多次
  • 错误随机出现在不同测试文件中,甚至会出现在未发起HTTP请求、未引入Axios的纯单元测试文件内
  • 错误发生在测试运行到1/2至3/4阶段,每次出错的文件都不固定
  • 已参考Supertest相关issue重构测试的启动/关闭流程,问题未解决
  • 错误无有效堆栈跟踪,无法定位来源

测试代码模式

const request = supertest(app);

describe("functionName", () => {
    it("should perform x", async () => {
      const res = await request.get("/v1/asset");
      const { result } = res.body;
      expect(res.status).toEqual(200);
      // 其他断言逻辑
    });
});

Express App示例

import express from "express";

const app = express();
app.get("/routes", (req, res) => {
    res.json({});
});

export default app;

运行环境

  • Node.js 20.16
  • Yarn 4.4.0
  • Jest 29.7.0
  • Supertest 6.3.4

调试排查方案

1. 开启Axios详细日志

在测试入口文件(如jest.setup.js)中添加Axios拦截器,捕获请求/响应/错误的完整信息:

const axios = require('axios');
// 记录请求详情
axios.interceptors.request.use(request => {
  console.log(`[AXIOS REQUEST] ${request.method?.toUpperCase()} ${request.url}`);
  return request;
});
// 记录错误详情
axios.interceptors.response.use(response => response, error => {
  console.error(`[AXIOS ERROR] ${error.response?.status || '未知状态'} 请求地址: ${error.config?.url}`);
  console.error('错误堆栈:', error.stack);
  throw error;
});

2. 禁用Jest并行测试

随机错误大概率和并行测试的资源冲突有关,先在jest.config.js中关闭并行:

module.exports = {
  // 其他配置项
  maxWorkers: 1,
  runInBand: true
};

若关闭并行后错误消失,说明是测试间的资源竞争(如端口占用、App实例状态污染、数据库连接未清理等)导致。

3. 给每个测试创建独立的App实例

当前所有测试共享同一个app实例,可能出现路由被覆盖、中间件状态污染的情况。修改App导出方式为创建实例的函数:

// app.js 修改后
import express from "express";

const createApp = () => {
  const app = express();
  app.get("/routes", (req, res) => {
      res.json({});
  });
  return app;
};

export { createApp };

测试文件中每次测试前生成新实例:

const { createApp } = require('../app');
const supertest = require('supertest');

describe("functionName", () => {
  let request;

  beforeEach(() => {
    const app = createApp();
    request = supertest(app);
  });

  it("should perform x", async () => {
    const res = await request.get("/v1/asset");
    expect(res.status).toEqual(200);
  });
});

4. 捕获全局未处理异常

在jest.setup.js中添加全局错误监听,捕获未被测试用例捕获的异常:

process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的Promise拒绝:', promise, '原因:', reason);
  process.exit(1);
});

process.on('uncaughtException', (error) => {
  console.error('未捕获的异常:', error);
  console.error('异常堆栈:', error.stack);
  process.exit(1);
});

5. 启用Jest详细调试参数

运行测试时添加以下参数,获取更详细的测试执行信息和未关闭资源检测:

yarn test --verbose --detectOpenHandles

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:50:11