按照承诺用 Chai 测试拒绝

Test a rejection with Chai as promised

我想测试一个返回承诺的函数。

在此特定测试中,promise 预计会被包含经典 message 字段(在此测试中,预计等于 "my error message")和自定义字段的错误对象拒绝我添加了named code,这是一个字符串(如"EACCESS"、"ERIGHT"等,在这个测试中它应该等于"EFOO"

我想像承诺的那样使用 chai。

return expect(foo()).to.eventually.be.rejectedWith("my error message");

此断言有效,但现在我也想测试 code 字段。
怎么做?

如果您正在使用 Chai-As-Promised(如您所说),那么它允许链接 rejectedWith - 并将链断言对象设置为错误对象 - 意思是rejectedWith() 之后的任何内容现在都将对错误进行断言。这让您可以做一些很酷的事情,例如:

return expect(foo()).to.eventually
  .be.rejectedWith("my error message")
  .and.be.an.instanceOf(Error)
  .and.have.property('code', 'EFOO');

一些 chai 方法也是链式的,因此您可以使用它来对错误进行一些嵌套很深的断言:

return expect(foo()).to.eventually
  .be.rejectedWith("my error message")
  .and.have.property('stack')
    .that.includes('myfile.js:30')

使用 ChaiAsPromised 5.1.0 版,Keithamus 的解决方案对我不起作用 - rejectedWith 没有给我断言的错误对象,但是 "rejected" 做到了:

return expect(foo())
    .to.be.rejected
    .and.be.an.instanceOf(Error)
    .and.have.property('code', 'EFOO');

用于断言多个属性

return expect(foo())
    .to.be.rejected
    .then(function(error) {
        expect(error).to.have.property('name', 'my error message');
        expect(error).to.have.property('code', 'EFOO');
    });

@Markko Paas 的解决方案在我添加 'eventually' 之前对我不起作用,否则被拒绝的值始终是 {} 空对象。

return expect(foo())
    .to.eventually.be.rejected
    .and.be.an.instanceOf(Error)
    .and.have.property('code', 'EFOO');

您可以使用 rejected.then:

对错误执行复杂的测试
it('throws a complex error', function () {
  return expect(foo()).to.eventually.be.rejected.then((error) => {
    expect(error.code).to.equal('expected code');
    // other tests
    // alternatively,
    expect (error).to.eql({
      foo: 'foo',
      bar: 'bar
    });
  });
});

Chai-As-Promised 对我不起作用,因为如果您希望某些东西被拒绝并且它不会拒绝,它不会抛出。

然后我使用了下面的,IMO也很有表现力:

//...
await $radioButton.click();

const executed = await(async () => {
    try {
        await tools.waitUntil(() => {
            return consoleMessages.length === 2;
        }, 1000); // 1000 is the timeout in milliseconds. waitUntil() rejects if it does timeout.
        return true;
    } catch (error) {
        return false;
    }
})();

chai.assert.strictEqual(executed, false);

在我的例子中,因为我在 async 函数中使用了 chai-as-promised,所以我所要做的就是在 expect(promise).to.be.rejectedWith(errorMessage) 之前添加一个 await 语句,例如:

it('should reject', async () => {
    await expect(promise).to.be.rejectedWith(errorMessage);
//  ^^^^^
});