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

Node.js Jest单元测试断言Error对象引号不匹配问题排查

Jest 断言异步Error对象失败解决方案

问题根因

  1. 断言失败和Jest输出的外层双引号无关:双引号是Jest控制台对字符串类型值的格式标记,不是预期值本身的内容。核心问题是你用toBe做严格相等判断时,一侧是字符串,另一侧是ConnectionError类型的Error实例,二者类型不同,永远不可能相等。
  2. 调用err.toString()/err.message触发TS的Object is of type unknown报错,是因为TypeScript中catch块捕获的错误默认类型为unknown,不允许直接访问unknown类型值的属性或方法。
  3. .toThrow不生效是用法错误:该匹配器默认匹配同步抛出的错误,匹配异步reject时需要搭配rejects使用,你之前直接传入已触发的异步Promise,没有走正确的异步断言流程,自然匹配不到错误。

可直接复用的正确写法

写法1:无try/catch 推荐写法

不需要手动捕获错误,直接用Jest内置的异步错误匹配器,记得给整个断言加await:

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });

    // 仅匹配错误信息
    await expect(
      exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO')
    ).rejects.toThrow('Login failed for user \'BAD_USER\'.');

    // 如果需要同时匹配错误码、错误类型等更多属性,用toMatchObject
    await expect(
      exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO')
    ).rejects.toMatchObject({
      code: 'ELOGIN',
      message: 'Login failed for user \'BAD_USER\'.'
    });

    await shutdown();
  });
});

写法2:手动try/catch 写法

如果需要自定义错误处理逻辑,先对捕获的err做类型断言,再访问属性,同时要加断言确保Promise确实走到了reject分支,避免用例假通过:

// 如果你项目里有导出tedious的ConnectionError类型可以直接导入,没有的话可以临时定义类型,或者直接断言为Error
import { ConnectionError } from 'tedious/lib/errors';

describe('aresFileCopier', () => {
  test('log error', async () => {
    await registerDB('ares-test', {
      client: 'mssql',
      connection: {
        host: 'test-mssql',
        database: 'master',
        user: 'BAD_USER',
        password: 'BAD_Password',
        port: 1433,
      },
    });

    try {
      await exec('ares-test', 'DROP TABLE IF EXISTS dbo.VW_EMPLOYEE_NAME_INFO');
      // 走到这里说明Promise没有reject,用例直接失败
      throw new Error('Expected exec method to throw login error, but it resolved successfully');
    } catch(err) {
      const loginErr = err as ConnectionError;
      expect(loginErr.message).toBe('Login failed for user \'BAD_USER\'.');
      expect(loginErr.code).toBe('ELOGIN');
    }

    await shutdown();
  });
});

避坑提示

  • 不要尝试修改Jest控制台的输出格式,外层双引号只是类型标识,修改控制台输出对断言逻辑没有任何帮助。
  • 所有带rejects/resolves的异步断言必须加await,否则Jest不会等待异步逻辑执行完成,会出现用例假通过的问题。
  • 你贴出的exec方法直接返回Promise,不需要额外包装,直接传入expect()即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:57:16