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

Posted

技术标签:

【中文标题】Mocha,应该 - 在测试具有承诺的异步函数时,断言错误是沉默的【英文标题】:Mocha, should - when testing async function that has promise in it, assertion errors are silent 【发布时间】:2017-03-29 10:05:21 【问题描述】:

我遇到了一个困扰我的小问题.. 以下代码显示了一个异步测试,在该测试中我们测试了我们无法控制的代码(测试的黑盒,我可以更改它)。

黑盒代码在完成后调度事件,测试监听该事件并断言数据。

问题是当出现断言错误时,异常是由 Promise 错误处理程序而不是由测试框架抛出和咳嗽的,所以 done 函数永远不会执行,并且我们会得到这个测试的超时错误。

在 it() 块中通过 try & catch 很容易解决这个问题,但是总是在 it() 块中 try & catch 是一个好习惯吗?到目前为止,我信任测试框架来处理异常

另一个问题是错误是无声的,除非 catch 打印它,而且由于它是黑盒,我们不能指望它。

这里的提示帮助我解决了这个问题,但我不喜欢这些解决方案: https://github.com/mochajs/mocha/issues/1128#issuecomment-40866763

它与其他类似问题不同,因为在 it() 块中,我们没有对 Promise 对象的任何引用。

describe.only("test", function () 

  var event;

  // blackbox simulates a code we have no controler over
  // inside this code we have a promise, when this promise resolves it triggers event
  var blackbox = function () 
    var promise = new Promise(function (resolve, reject) 
      resolve();
    );

    promise.then(function () 
      event(4);
    ).catch(function (e) 
      console.log(e);
    );
  ;

  it("async with blackbox promise", function (done) 
    // this simulates event listenner, when the event is triggered the code executes
    event = function (data) 
      // this assertion works and everything is fine
      data.should.be.equal(4);
      // this assertion thrown exception that is being cought by the promise reject handler and
      // isnt cought by the testing framework (chai / mocha)
      data.should.be.equal(5);
      // because the exception is thrown we never reach the done
      done();
    ;

    blackbox();

  );
);

【问题讨论】:

我认为你混淆了一些东西。始终返回您的承诺,并且在测试承诺时,您不需要 done 回调。只要回报你所有的承诺。 另外请注意,如果您希望 mocha 在被拒绝的 promise 上失败,那么您不必自己 catch @MarcoL,这只是一个例子,因为代码是黑盒的——我无法控制它。它可以是第 3 方库/依赖项,还是说黑盒示例代码写错了? 如果代码(来自第 3 方或黑盒)处理承诺,那么它应该向您返回承诺。 如果黑盒没有返回任何东西,你就不能在这里进行异步测试。此外,如果它没有为您提供处理它们的选项,那么它在内部使用 Promises 而不是回调这一事实根本不重要。 【参考方案1】:

您在mocha 中测试 Promise 的方式是返回它们并让它完成决定何时失败或不失败的工作。

所以第一步是在你的blackbox 函数中提供promise:

// blackbox simulates a code we have no controler over
// inside this code we have a promise, when this promise resolves it triggers event
var blackbox = function () 
  var promise = new Promise(function (resolve, reject) 
    resolve();
  );

  return promise.then(function () 
    event(4);
  );
  // do not catch here unless you want the test to not fail on error
;

现在让我们更改测试代码来处理 Promise:

it("async with blackbox promise", function () 
  // this simulates event listenner, when the event is triggered the code executes
  event = function (data) 
    // this assertion works and everything is fine
    data.should.be.equal(4);
    // this assertion thrown exception that is being cought by the promise reject handler
    data.should.be.equal(5);
  ;
  // mocha will append a rejection handler to this promise here and fail if it gets called
  return blackbox();

);

【讨论】:

以上是关于Mocha,应该 - 在测试具有承诺的异步函数时,断言错误是沉默的的主要内容,如果未能解决你的问题,请参考以下文章

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

断言正在破坏 Mocha 测试中的异步功能

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

使用 Mocha 测试 Promise 时发生错误

使用 mocha 和 chaiAsPromised 测试异步函数时的断言错误

在mocha测试中调用异步函数如何避免超时错误:超过2000ms的超时