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

使用Mocha与Chai测试Node.js API路由时遭遇超时故障求助

解决Mocha测试API路由超时问题及代码优化建议

你遇到的测试超时问题,大概率是异步操作耗时超出Mocha默认阈值,再加上路由和测试代码里的几个小逻辑漏洞导致的,我来帮你一步步梳理解决:

一、先搞定测试超时问题

Mocha默认给异步测试的超时时间只有2000ms,而文件上传+数据库存储的操作很容易超过这个时长。你可以给测试用例单独设置更长的超时时间:

describe('POST /content/image_upload', () => {
  // 给整个测试块设置10秒超时,根据实际情况调整
  this.timeout(10000);
  
  it('should return status 200', async function() {
    // 如果用箭头函数拿不到this,也可以在这里单独设置
    // this.timeout(10000);
    // ... 你的测试代码
  })
})

二、修复路由处理器的逻辑漏洞

你的路由代码有几个可能导致响应卡住或重复发送的问题:

1. 条件判断后未加return,可能触发多次响应

比如当检测到参数缺失时,你发送了400响应,但代码会继续往下执行,后续可能又发送一次响应,导致Node.js报错,测试也会因为响应异常而超时。修改成:

if(files == undefined || originalUrls == undefined){
  return res.status(400).send({status:'failed', message:"input field cannot be undefined"})
}

同理,最后else分支也加上return:

}else{
  return res.status(400).send({status:'failed', message:"input error"})
}

2. 兼容单个文件/单个URL的情况

当用户只上传一个文件时,req.files['files[]']可能是单个对象而非数组;同理originalUrls如果是单个字符串,originalUrls.length会是字符串长度而非数组长度,导致判断错误。先统一转成数组:

// 统一处理成数组格式
files = Array.isArray(files) ? files : [files];
originalUrls = Array.isArray(originalUrls) ? originalUrls : [originalUrls];

3. 校验文件和URL数量匹配

如果上传的文件数和URL数不一致,会导致originalUrls[index]为undefined,建议增加校验:

if(files.length !== originalUrls.length){
  return res.status(400).send({status:'failed', message:"number of files must match number of original urls"})
}

三、优化测试代码

1. 无需手动设置Content-Type

chai-http的attach和field会自动生成正确的multipart/form-data请求头,手动设置反而可能出错,删掉这一行:

.set('Content-Type', 'application/form-data')

2. 修正attach的文件名参数

attach的第三个参数应该是文件的原始名称,比如:

.attach('files[]', fs.readFileSync(path.join(__dirname,'./asset/listEvent.png')), 'listEvent.png')

完整修改后的路由处理器示例

exports.imageUpload = (req, res, next) => { 
  Upload(req,res, async () => { 
    let files = req.files['files[]']; 
    let originalUrls = req.body.orgUrl; 

    // 校验必填参数
    if(files == undefined || originalUrls == undefined){
      return res.status(400).send({status:'failed', message:"input field cannot be undefined"})
    }

    // 统一转为数组格式
    files = Array.isArray(files) ? files : [files];
    originalUrls = Array.isArray(originalUrls) ? originalUrls : [originalUrls];

    // 校验数量匹配
    if(files.length !== originalUrls.length){
      return res.status(400).send({status:'failed', message:"number of files must match number of original urls"})
    }

    if(files.length > 0){ 
      const promises = files.map(async(file,index)=>{ 
        const imageDoc = new ImageModel({ 
          croppedImageUrl : file.path, 
          originalImageUrl: originalUrls[index], 
          status: 'New' 
        }); 
        return await imageDoc.save(); 
      }); 

      try{ 
        const response = await Promise.all(promises); 
        return res.status(200).send({status: 'success', res: response}); 
      }catch(error){ 
        return res.status(500).send({status:"failed", error: error.message}) // 返回更友好的错误信息
      } 
    }else{ 
      return res.status(400).send({status:'failed', message:"input error"}) 
    } 
  }) 
}

完整修改后的测试代码示例

describe('POST /content/image_upload', () => {
  this.timeout(10000);

  it('should return status 200', async function() {
    const response = await chai.request(app)
      .post('/content/image_upload')
      .attach('files[]', fs.readFileSync(path.join(__dirname,'./asset/listEvent.png')), 'listEvent.png')
      .field('orgUrl', 'https://images.unsplash.com/photo-1556830805-7cec0906aee6?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1534&q=80')

    expect(response.error).to.be.false;
    expect(response.status).to.be.equal(200);
    expect(response.body.status).to.be.equal('success');
    response.body.res.forEach(item => {
      expect(item).to.have.property('croppedImageUrl');
      expect(item).to.have.property('originalImageUrl');
      expect(item).to.have.property('status');
      expect(item).to.have.property('_id');
    })
  })
})

按照这些修改,应该能解决超时问题,同时修复路由里的逻辑漏洞,让测试顺利通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:53:13