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
相关产品推荐
相关产品推荐

