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

如何使用Mocha测试多个Promise?

问题:测试多个Promise时Mocha报错(done()被多次调用+方法冲突)

我正在测试request-image-size库返回的Promise:传入图片URL后会得到尺寸响应,打不开图片则返回错误。

我的test.js测试用例如下:

describe('Test images', () => {
  it('Should test all image sizes',async (done) => {

   const imagesResonses = await getAllImageResponses(imagesURLs)

      // 打印imageResponses会得到一个Promise数组,其中两个应被拒绝并抛出错误
      // [
      //   Promise { <pending> },
      //   Promise { <pending> },
      //   Promise { <pending> },
      //   Promise { <pending> },
      //   Promise { <pending> },
      //   Promise { <pending> }
      // ]
      imagesResonses.map((image) => image.then((res) => {
        console.log(res)
        assert(res.height > 0, 'height must be greater than zero');
        done()
      }).catch((err) => {
        console.log(err)
        done(err)
      }))
  })

测试时出现以下错误:

done() called multiple times in test <Test links and images S
should test all image sizes> of file C:path/test.js; in addition, don
e() received error: Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

需求:对每个Promise执行断言,Promise被拒绝时记录错误。


错误原因分析

  1. 方法冲突:你同时使用了async函数(本身会返回Promise)和done回调,Mocha不允许同时用这两种方式标记测试结束,二选一即可。
  2. done()被多次调用:你在每个Promise的then/catch回调里都调用了done,数组有多少个Promise就会调用多少次done,但Mocha要求每个测试只能调用一次done。

解决方案

方案1:用Promise.allSettled逐个处理成功/失败结果

适合需要分别处理每个Promise的成功和失败场景(比如允许部分图片加载失败,只记录错误):

describe('Test images', () => {
  it('Should test all image sizes', async () => {
    // 注意:这里不需要提前await,直接获取Promise数组即可
    const imagePromises = getAllImageResponses(imagesURLs);
    // 等待所有Promise完成(无论成功/失败)
    const results = await Promise.allSettled(imagePromises);

    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        const res = result.value;
        console.log(`图片${index+1}成功:`, res);
        assert(res.height > 0, `图片${index+1}高度必须大于0`);
      } else {
        const err = result.reason;
        console.log(`图片${index+1}加载失败:`, err);
        // 若要求所有图片必须成功,可在此抛出错误终止测试
        // throw new Error(`图片${index+1}加载失败:${err.message}`);
      }
    });
  })
})

方案2:用Promise.all要求所有Promise必须成功

如果所有图片都必须成功获取尺寸,用Promise.all更简洁(只要有一个Promise失败,测试直接终止):

describe('Test images', () => {
  it('Should test all image sizes', async () => {
    // 等待所有Promise成功,失败则直接抛出错误
    const imageResults = await Promise.all(getAllImageResponses(imagesURLs));
    
    imageResults.forEach((res, index) => {
      console.log(`图片${index+1}结果:`, res);
      assert(res.height > 0, `图片${index+1}高度必须大于0`);
    });
  })
})

关键修改点

  • 移除async函数的done参数,async函数返回的Promise会被Mocha自动识别,无需手动调用done。
  • 用Promise.all/Promise.allSettled统一处理Promise数组,避免多次触发测试结束逻辑。
  • 遍历结果数组做断言,不要在单个Promise的回调里直接结束测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:05:32