18

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

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

但是,这不适用于此并返回:

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

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

4

4 回答 4

30

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

与 chai-as-promised

以下是如何使用 chai-as-promised 来测试Promiseresolve和case 的方法:reject

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'); })
            ;
});
于 2016-05-14T04:03:43.083 回答
10

我个人使用这个成语:

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

于 2018-01-05T18:51:34.673 回答
5

您收到错误是因为 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');
  });
于 2015-08-06T01:31:19.620 回答
-1

我也遇到过同样的问题,但是在做了很多 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 世界的新手

于 2017-07-21T06:38:11.323 回答