按照承诺与 Chai 测试拒绝

问题描述 投票:0回答:7

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

在这个特定的测试中,预计 Promise 会被包含经典

message
字段的 Error 对象(在这个测试中,预计等于
"my error message"
)和我添加的名为
code
的自定义字段拒绝,其中是一个字符串(如“EACCESS”、“ERIGHT”等,在此测试中它预计等于
"EFOO"

我想使用 chai-as-promised 来实现这一点。

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

这个断言有效,但现在我也想测试

code
字段。
如何做到这一点?

javascript chai
7个回答
67
投票

如果您使用 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')

41
投票

有了 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');
    });

13
投票

@Markko Paas 的解决方案对我不起作用,直到我添加“最终”,否则拒绝的值始终是 {} 空对象。

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

8
投票

您可以使用

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
    });
  });
});

8
投票

就我而言,由于我在

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

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

1
投票

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);


0
投票

使用 then 和 catch 来避免这些问题。

it('should handle error during company details retrieval', async () => {
    const companyId = mongoose.Types.ObjectId();
    const params = {
      startDate: Date.now() - 7 * 24 * 3600 * 1000, // 7 days ago
      endDate: Date.now(),
    };

    const companyStub = sinon
      .stub(Company, 'findById')
      .rejects(new Error('Database error'));

    companyDashBoardInfo(companyId, params).then((result) => {
      expect(result).to.be.rejectedWith(InternalServerException);
      expect(
        companyStub.calledOnceWithExactly(companyId, {
          _id: 1,
          accountAccess: 1,
        }),
      ).to.be.true;
    });
  });
© www.soinside.com 2019 - 2024. All rights reserved.