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

如何测试预期抛出异常的异步方法?Mocha测试未生效

问题分析与修复方案

你的测试没捕获到预期异常的核心原因是:invoke方法里的错误没有被正确关联到它返回的Promise上。

为什么会出现这个问题?

你标记了invoke为async函数,所以它会自动返回一个Promise,但你内部用的是回调式的fs.readFile——当fs.readFile调用完成后(只是发起了读取请求,还没执行回调),async函数就已经执行完毕,返回的Promise被直接resolve为undefined了。而回调里抛出的错误属于另一个异步调用栈,根本无法被这个Promise捕获,所以Mocha会认为Promise被fulfilled,而不是rejected。

修复方案:让错误正确关联到Promise

有两种常见的修复方式,选哪种都可以:

方案1:使用Promise版的文件读取API

Node.js的fs模块已经提供了Promise风格的API(fs.promises),直接用它就能让错误自动被Promise捕获:

import fs from 'fs/promises';

public async invoke(): Promise<void> {
  try {
    await fs.readFile(this.templatePath);
  } catch (outerError) {
    throw new Error(`FileNotFoundException: Cannot find file \`${this.templatePath}'.`);
  }
}

这样,当文件不存在时,fs.promises.readFile会返回一个rejected的Promise,await会把这个错误抛出来,我们自定义错误信息后再抛出,这个错误会被async函数返回的Promise捕获,测试就能正确断言了。

方案2:手动用Promise包裹回调式API

如果你不想切换到Promise版API,可以手动把回调式的fs.readFile包裹在Promise里:

import fs from 'fs';

public async invoke(): Promise<void> {
  return new Promise((resolve, reject) => {
    fs.readFile(this.templatePath, (outerError: NodeJS.ErrnoException, data: Buffer): void => {
      if (outerError !== null) {
        reject(new Error(`FileNotFoundException: Cannot find file \`${this.templatePath}'.`));
        return;
      }
      resolve();
    });
  });
}

这里我们手动创建了一个Promise,当文件读取失败时调用reject传递错误,成功时调用resolve。这样invoke返回的Promise就会正确关联到异步操作的结果,测试就能捕获到rejected状态了。

测试代码无需修改

你的原测试代码是没问题的,只要修复了invoke方法,它就能正确断言Promise被Error拒绝:

it("should throw when the template file does not exist", async (): Promise<void> => { 
  await expect(new UpdateReadmeCommandlet().invoke()).to.be.rejectedWith(Error); 
});

这样修改后,Mocha就能正确捕获到预期的异常,不会再出现AssertionError了,而且也不会影响其他测试的执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:14:46