使用 mocha 的内置承诺支持测试失败的承诺 [重复]

Posted

技术标签:

【中文标题】使用 mocha 的内置承诺支持测试失败的承诺 [重复]【英文标题】:testing failed promises with mocha's built-in promise support [duplicate] 【发布时间】:2015-04-26 14:34:02 【问题描述】:

我应该如何使用 mocha 和 chai 测试我的承诺是否失败?

我很困惑,因为我最初认为我应该使用“mocha-as-promised”,但那 包现在已弃用(我使用的是 mocha 2.1.0),建议 只需使用现在内置于 mocha 中的 Promise 测试。 见:https://github.com/domenic/mocha-as-promised

另一篇文章建议取消 it() 回调 - 不知道为什么,因为我理解 传入“完成”参数是表示测试已完成的方式 被异步测试。 见:How do I properly test promises with mocha and chai?

无论如何,我已经尝试将我的问题简化为以下代码 - 请帮助我修改它,以便我可以测试我的承诺确实失败了。

it.only("do something (negative test)", function (done) 

  var Q = require('q');

  function makePromise() 
    var deferred = Q.defer();
    deferred.reject(Error('fail'));
    return deferred.promise;
  ;

  makePromise()
  .then(done, done);

);

【问题讨论】:

【参考方案1】:

更多挖掘,似乎正确的方法是添加一个额外的 catch 块,就像这样......

it.only("do something (negative test)", function (done) 

  var Q = require('q');

  function makePromise() 
    var deferred = Q.defer();
    deferred.reject(Error('fail'));
    return deferred.promise;
  ;

  makePromise()
  .catch(function(e) 
    expect(e.message).to.equal('fail');
  )
  .then(done, done);

);

我对替代想法感兴趣,或者确认这很好。谢谢。

更新:

Ben - 我现在明白你在说什么,尤其是。在 Benjamin G.

简短而有用的评论之后

总结一下:

当您传入done 参数时,测试预计会通过调用done() 函数来触发它的“完成”;

当你不传入done 参数时,它通常只适用于同步调用。然而, 如果您返回一个承诺,mocha 框架 (mocha >1.18) 将捕获通常会被吞下的任何故障(根据承诺规范)。这是一个更新的版本:

it.only("standalone neg test for mocha+promises", function () 

  var Q = require('q');

  function makePromise() 
    var deferred = Q.defer();
    deferred.reject(Error('fail'));
    return deferred.promise;
  ;

  return makePromise()
  .catch(function(e) 
    expect(e.message).to.equal('fail');
  );

);

【讨论】:

您可以return makePromise() 并删除done, done 部分。 我会添加一个额外的断言以确保它没有达到验收案例。 return makePromise() .then(() => // Acceptance case, we should not get here. expect().fail('exception did not appear to be thrown'); , (e) => // Failure case, we should get here and the message shoudl match expect(e.message).to.equal('fail'); ); 【参考方案2】:

您可以返回一个承诺来表明测试是异步的:

function something() 
  return Q.reject(Error('fail'));


it('should reject', function() 
  return something().then(function() 
    throw new Error('expected rejection');
  ,
  function() 
    return 'passed :]';
  );
);

【讨论】:

【参考方案3】:

chai-as-promised 为 Promises 提供了一个干净的测试框架:

$ npm install chai-as-promised

在您的测试文件中:

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('resolved as promised', function() 
    return Promise.resolve("woof")
        .then(function(m)  expect(m).to.equal('woof'); )
        .catch(function(m)  throw new Error('was not supposed to fail'); )
            ;
);

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,我的异步方法返回延迟库的承诺 (npmjs.com/package/deferred)。当我运行测试时,我遇到了错误。这个mudule支持deferred吗? “TypeError:无法读取未定义的属性‘then’” @PiyushBeli:确保“提供”then 的表单返回一个承诺。例如,确保它有一个 return 语句。

以上是关于使用 mocha 的内置承诺支持测试失败的承诺 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

嵌套承诺 - 摩卡 - 超过超时

Mocha 在运行测试之前似乎没有等待承诺链完成

Mocha,应该 - 在测试具有承诺的异步函数时,断言错误是沉默的

尽管使用 done,Mocha 在 Before 钩子中调用异步承诺链超时

Chai + mocha,解决则测试成功,拒绝则失败

使用 Mocha 测试 Promise 时发生错误