【问题标题】:Testing rejected promise in Mocha/Chai在 Mocha/Chai 中测试被拒绝的承诺
【发布时间】:2015-10-28 23:39:46
【问题描述】:

我有一个拒绝承诺的课程:

Sync.prototype.doCall = function(verb, method, data) {
  var self = this;

  self.client = P.promisifyAll(new Client());

  var res = this.queue.then(function() {
    return self.client.callAsync(verb, method, data)
      .then(function(res) {
        return;
      })
      .catch(function(err) {    
        // This is what gets called in my test    
        return P.reject('Boo');
      });
  });

  this.queue = res.delay(this.options.throttle * 1000);
  return res;
};

Sync.prototype.sendNote = function(data) {
  var self = this;
  return self.doCall('POST', '/Invoice', {
    Invoice: data
  }).then(function(res) {
    return data;
  });
};

在我的测试中:

return expect(s.sendNote(data)).to.eventually.be.rejectedWith('Boo');

但是,当测试通过时,它会将错误抛出到控制台。

未处理的拒绝错误:嘘 ...

对于非承诺错误,我使用了 bind 来测试以防止错误被抛出,直到 Chai 可以包装和测试:

return expect(s.sendNote.bind(s, data)).to.eventually.be.rejectedWith('Boo');

但是这不适用于 this 并返回:

类型错误:[Function] is not a thenable.

对此进行测试的正确方法是什么?

【问题讨论】:

    标签: javascript promise mocha.js bluebird chai-as-promised


    【解决方案1】:

    (免责声明:即使对于不使用 Bluebird 的人来说,这也是一个很好的问题。我已经发布了类似的答案 here;这个答案适用于不使用 Bluebird 的人。)

    按照承诺使用 chai

    以下是如何使用 chai-as-promised 来测试 resolvereject 的 Promise 案例:

    var chai = require('chai');
    var expect = chai.expect;
    var chaiAsPromised = require("chai-as-promised");
    chai.use(chaiAsPromised);
    
    ...
    
    it('resolves as promised', function() {
        return expect(Promise.resolve('woof')).to.eventually.equal('woof');
    });
    
    it('rejects as promised', function() {
        return expect(Promise.reject('caw')).to.be.rejectedWith('caw');
    });
    

    没有承诺的柴

    你可以在没有 chai-as-promised 的情况下完成同样的事情:

    it('resolves as promised', function() {
      return Promise.resolve("woof")
        .then(function(m) { expect(m).to.equal('woof'); })
        .catch(function(e) { throw e })  // use error thrown by test suite
               ;
    });
    
    it('rejects as promised', function() {
        return Promise.reject("caw")
            .then(function(m) { throw new Error('was not supposed to succeed'); })
            .catch(function(m) { expect(m).to.equal('caw'); })
                ;
    });
    

    【讨论】:

    • 不使用chai-as-promised,您可以改为抛出测试套件生成的错误。 .catch(function(e) { throw e });
    • @IliasT - 你非常正确,我已经采纳了你的建议。希望你不要介意! :)
    【解决方案2】:

    我个人使用这个成语:

    it('rejects as promised', function() {
        return Promise.reject("caw")
            .then(
              (m) => { assert.fail('was not supposed to succeed'); }
              (m) => { /* some extra tests here */ }
            );
    });
    

    这是then(onFulfilled, onRejected)(2 个参数)合法使用的少数情况之一。

    如果您按照其他答案中的建议链接.then(reject).catch(onRejected),您最终会每次都输入catch 处理程序,因为它也会捕获前面then 处理程序中产生的拒绝--如果你不仔细检查这种可能性,这可能会导致常绿测试。

    【讨论】:

      【解决方案3】:

      您收到错误是因为 sendNote 被拒绝而您没有收到它。

      试试:

      var callPromise = self.doCall('POST', '/Invoice', {
        Invoice: data
      }).then(function(res) {
        return data;
      });
      
      callPromise.catch(function(reason) {
        console.info('sendNote failed with reason:', reason);
      });
      
      return callPromise;
      

      看起来您还必须将现有的 catch 移出一个街区:

      var res = this.queue.then(function() {
        return self.client.callAsync(verb, method, data)
          .then(function(res) {
            return;
          });
        }).catch(function(err) {    
          // This is what gets called in my test    
          return P.reject('Boo');
        });
      

      【讨论】:

      • 这似乎没有任何改变。仍然在控制台上转储错误
      • 我认为这与队列有关。如果我只是从doCall 函数中执行return P.reject(),它就可以工作
      • 啊。将鱼钩移出一格。
      • 是的 - 我在 res.delay 调用中添加了一个捕获,它起作用了。甜的!如果你会更新你的答案,我会标记它。
      • then 块什么都不做,可以删除。
      【解决方案4】:

      我也遇到过同样的问题,但是在做了很多 hack 之后,我找到了一个在 mocha 中测试被拒绝的 Promise 的解决方案。

      如下写mocha代码

      it('works with resolved and rejected promises', function() {
       return yourPromiseFunction("paramifrequired")
             .then((result)=>{
                  //check with should or expect
             }).catch((result)=>{
                  //check with should or expect whether it's rejected with proper result status. set result status in promise function while rejecting accordingly
             })
      
        });
      

      注意:- 希望你觉得它有用。如果您有其他想法建议请评论我,我是探索 js 世界的新手

      【讨论】:

      • this answer posted one year before yours 尚未提供的这个答案提供了什么?
      • 我认为我的代码更清晰、更简短,给出了解决它的想法,而不是上面的代码,这让我感到困惑,因为我是新手,而不是专家。我发布了这个答案,以便另一个新手可以快速获得它,而不是看到大代码。
      • 我认为这不适用于测试被拒绝的承诺,因为如果被拒绝的承诺确实通过了,catch 函数中的断言将不起作用。
      猜你喜欢
      • 2015-06-04
      • 2017-07-16
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多