【问题标题】:Test a rejection with Chai as promised按照承诺用 Chai 测试拒绝
【发布时间】:2015-06-04 11:40:28
【问题描述】:

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

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

我想为此使用 chai-as-promised。

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

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

【问题讨论】:

标签: javascript chai


【解决方案1】:

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

【讨论】:

  • 由于某种原因这对我不起作用。无论我做什么错误消息字符串它总是通过。
  • @chovy 能不能把 foo() 的方法代码贴一下。如果您使用返回语句和拒绝处理程序,您可以验证您的测试系统(方法),如果您明确拒绝...否则承诺将被视为已解决。
  • foo() 正在返回 $q.defer().promise - 显然 chai-as-promised 与 angular 的 $q 存在问题。
  • @chovy 你需要返回expect函数,否则它不会工作。在过去的 30 分钟里,我一直在敲我的头,直到我注意到我忘了返回,现在它对我有用。
  • @ChristianSaiki 非常感谢!在过去的 20 分钟里,我一直在为完全相同的问题撞墙。
【解决方案2】:

拥有 5.1.0 版的 ChaiAsPromised,Keithamus 的解决方案对我不起作用 - deniedWith 没有给我断言的错误对象,但“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');
    });

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您可以使用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
          });
        });
      });
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 在断言前面添加 await 也对我有用
        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-28
          • 1970-01-01
          • 1970-01-01
          • 2016-06-19
          • 1970-01-01
          • 2018-02-25
          • 2019-08-27
          • 2017-07-16
          相关资源
          最近更新 更多