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

Chai rejectedWith链式调用失效问题排查求助

问题

我查阅了大量帖子和文档,仍无法理解为何以下代码未按预期运行。

const chai = require('chai');
const expect = chai.expect;
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);

async function foo(val) {

    if (!val) {
        const err = new Error();
        err.status = 404;
        throw err;
    }

    return new Promise(resolve => sleepSetTimeout_ctrl = setTimeout(resolve, 10));
}

describe('does not work', () => {
    it('throws', async () => {
        await expect(foo()).to.be.rejectedWith(Error).and.have.property('status');
    });
});

当断言仅写到rejectedWith(Error)时可正常工作,但测试错误对象是否存在status属性时,会抛出断言错误:AssertionError: expected {} to have property 'status'。

原因与解决方法

问题出在rejectedWith的链式调用逻辑上:

  • rejectedWith(Error)返回的断言对象,默认不会把被拒绝的错误对象传递给后续的.and.have.property断言,而是传递了一个空对象,这是chai-as-promised的特性限制。
  • 要正确断言被拒绝错误的属性,需要调整断言写法,让后续断言指向实际的错误对象。

正确写法1:用eventually关联错误对象

await expect(foo()).to.be.rejectedWith(Error).and.eventually.have.property('status');

正确写法2:捕获错误后直接断言

try {
    await foo();
    expect.fail('Expected foo to reject');
} catch (err) {
    expect(err).to.be.an.instanceOf(Error);
    expect(err).to.have.property('status', 404);
}

正确写法3:用rejected替代rejectedWith做链式断言

// 仅验证属性
await expect(foo()).to.be.rejected.and.have.property('status');

// 同时验证错误类型和属性
await expect(foo()).to.be.rejectedWith(Error).and.be.an.instanceOf(Error).and.have.property('status');

核心逻辑是:rejectedWith本身侧重验证错误类型,链式调用时需要通过eventually明确指向被拒绝的实际值(错误对象),或者直接捕获错误后断言,才能正确访问到status属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:52:34