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

Jest异步测试中自定义异常显示为[object Object]的解决办法

问题

我正在为Jest测试创建一个用于存储请求失败信息的自定义错误类ApiError,代码如下:

/**
 * Custom error class for errors that happen when fetching data
 */
class ApiError extends Error {
  error: string;
  code: number | null;

  /**
   * Custom error class for errors that happen when fetching data
   */
  constructor (code: number | null, error: string) {
    super(error);
    this.error = error;
    this.code = code;
  }
}

export default ApiError;

但发现在异步代码中抛出该错误以拒绝Promise时,Jest会将其格式化为[object Object],示例报错信息如下:

● /auth/register › allows users to register

    [object Object]

      78 |     // All 400 and 403 errors have an error message
      79 |     const errorMessage = (json as { error: string }).error;
    > 80 |     throw new ApiError(res.status, errorMessage);
         |           ^
      81 |   }
      82 |   if (![200, 304].includes(res.status)) {
      83 |     // Unknown error

      at apiFetch (tests/api/fetch.ts:80:11)
      at Object.<anonymous> (tests/auth/register.test.ts:5:27)

这导致难以查看具体错误信息。我尝试添加toString()方法:

toString() {
  return `ApiError: [${this.code}] ${this.error}`;
}

但调试发现该方法并未被调用,请问如何让Jest像处理其他错误类型一样打印出可读的错误格式?


解决方案

自定义Error类在TypeScript中必须正确设置原型链,否则Jest无法将其识别为标准Error类型,导致默认格式化输出[object Object]。同时Jest处理异步错误时,优先读取name和message属性,而非直接调用toString()。按以下方式修改即可解决问题:

  • 修正原型链
    在构造函数中添加Object.setPrototypeOf(this, ApiError.prototype);,确保自定义错误继承Error的原型方法——这是TypeScript继承内置Error类的必要操作:

    constructor(code: number | null, error: string) {
      super(error);
      this.error = error;
      this.code = code;
      Object.setPrototypeOf(this, ApiError.prototype);
    }
    
  • 添加错误名称
    显式设置name属性为类名,让错误类型更清晰:

    name: string = 'ApiError';
    
  • 优化错误信息展示
    直接在父类构造函数中传入包含状态码的完整信息,让Jest输出的错误信息直接包含关键内容:

    constructor(code: number | null, error: string) {
      super(`[${code}] ${error}`);
      this.error = error;
      this.code = code;
      Object.setPrototypeOf(this, ApiError.prototype);
      this.name = 'ApiError';
    }
    

修改后的完整ApiError类示例:

/**
 * Custom error class for errors that happen when fetching data
 */
class ApiError extends Error {
  error: string;
  code: number | null;
  name: string = 'ApiError';

  constructor(code: number | null, error: string) {
    super(`[${code}] ${error}`);
    this.error = error;
    this.code = code;
    Object.setPrototypeOf(this, ApiError.prototype);
  }

  toString() {
    return `${this.name}: ${this.message}`;
  }
}

export default ApiError;

修改后,Jest捕获到ApiError时会输出类似如下的可读信息:

● /auth/register › allows users to register

  ApiError: [400] Username already exists

  ... 栈跟踪信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:18:20