简体   繁体   English

Mocha如何知道异步测试中的测试失败?

[英]How does Mocha know about test failure in an asynchronous test?

I am trying to understand how the asynchronous code for Mocha (at http://mochajs.org/#getting-started ) works. 我试图了解Mocha的异步代码( http://mochajs.org/#getting-started )是如何工作的。

describe('User', function() {
  describe('#save()', function() {
    it('should save without error', function(done) {
      var user = new User('Luna');
      user.save(function(err) {
        if (err) throw err;
        done();
      });
    });
  });
});

I want to know how Mocha decides whether a test has succeeded or failed behind the scenes. 我想知道Mocha如何决定测试在幕后是成功还是失败。

I can understand from the above code that user.save() being asynchronous would return immediately. 我可以从上面的代码中理解,异步的user.save()会立即返回。 So Mocha would not decide if the test has succeeded or failed after it executes it() . 因此,在执行测试后,Mocha不会决定测试是成功还是失败it() When user.save() ends up calling done() successfully, that's when Mocha would consider it to be a successful test. user.save()最终成功调用done() ,那就是当Mocha认为它是一个成功的测试时。

I cannot understand how it Mocha would ever come to know about a test failure in the above case. 我无法理解摩卡在上述情况下如何了解测试失败。 Say, user.save() calls its callback with the err argument set, then the callback throws an error. user.save()说, user.save()使用err参数集调用其回调,然后回调引发错误。 None of Mocha's function was called in this case. 在这种情况下,没有调用Mocha的函数。 Then how would Mocha know that an error occurred in the callback? 那么摩卡怎么会知道回调中发生了错误?

Mocha is able to detect failures that prevent calling the callback or returning a promise because it uses process.on('uncaughtException', ...); Mocha能够检测到阻止调用回调或返回promise的失败,因为它使用process.on('uncaughtException', ...); to detect exceptions which are not caught. 检测未捕获的异常。 Since it runs all tests serially, it always knows to which test an uncaught exception belongs. 由于它以串行方式运行所有测试,因此它始终知道未捕获的异常属于哪个测试。 (Sometimes people are confused by this: telling Mocha a test is asynchronous does not mean Mocha will run it in parallel with other tests. It just tells Mocha it should wait for a callback or a promise.) (有时人们对此感到困惑:告诉Mocha一个测试是异步的并不意味着Mocha将与其他测试并行运行。它只是告诉Mocha它应该等待回调或承诺。)

Unless there is something that intervenes to swallow exceptions, Mocha will know that the test failed and will report the error as soon as it detects it. 除非存在干预异常的内容,否则Mocha会知道测试失败并在检测到错误时立即报告错误。 Here is an illustration. 这是一个例子。 The first test fails due to a generic exception thrown. 由于抛出了一般异常,第一次测试失败。 The 2nd one fails due to an expect check that failed. 由于expect检查失败,第二个失败。 It also raises an unhandled exception. 它还引发了一个未处理的异常。

var chai = require("chai");
var expect = chai.expect;

it("failing test", function (done) {
    setTimeout(function () {
        throw new Error("pow!");
        done();
    }, 1000);
});

it("failing expect", function (done) {
    setTimeout(function () {
        expect(1).to.equal(2);
        done();
    }, 1000);
});

This is the output on my console: 这是我的控制台上的输出:

  1) failing test
  2) failing expect

  0 passing (2s)
  2 failing

  1)  failing test:
     Uncaught Error: pow!
      at null._onTimeout (test.js:6:15)

  2)  failing expect:

      Uncaught AssertionError: expected 1 to equal 2
      + expected - actual

      -1
      +2

      at null._onTimeout (test.js:13:22)

The stack traces point to the correct code lines. 堆栈跟踪指向正确的代码行。 If the exceptions happened deeper, the stack would be fuller. 如果异常发生得更深,那么堆栈会更充分。

When Mocha cannot report what went wrong exactly, that's usually because there is intervening code that swallows the exception that was raised. 当Mocha无法准确报告出错时,通常是因为有干预代码吞噬了引发的异常。 Or when you use promises the problem may be that someone forgot to call a method that indicates whether the promise is supposed to be completely processed and unhandled exceptions should be thrown. 或者当你使用promises时,问题可能是有人忘了调用一个方法来指示是否应该完全处理promise,并且应该抛出未处理的异常。 (How you do this depends on the promise implementation you use.) (如何执行此操作取决于您使用的promise实现。)

It won't, it's a shame. 它不会,这是一种耻辱。 It has no way to know that your callback is executing. 它无法知道您的回调正在执行。 It's an easier way to do asynchronous testing, where you just tell the test when you are finished. 这是一种更简单的异步测试方法,您可以在完成时告诉测试。 The downside, as you have noticed, is that errors in asynchronous callbacks won't be detected. 正如您所注意到的,缺点是不会检测到异步回调中的错误。 Nevermind, Mocha hooks to process.on('uncaughtException',...) as mentioned by Louis . 没关系,Mocha挂钩到如路易斯所提到的process.on('uncaughtException',...) Note that if you use done instead of waitsFor and runs in jasmine, then you will have the problem . 请注意,如果您使用done而不是waitsFor并在jasmine中runs那么您将遇到问题

Other frameworks like js-test-driver force to you wrap callbacks so the the testing framework can put a try catch around your callbacks (and you don't need to call done). 像js-test-driver这样的其他框架会强制你回调,所以测试框架可以try catch你的回调(并且你不需要调用done)。 Your test would look like the following: 您的测试将如下所示:

var AsynchronousTest = AsyncTestCase('User');

AsynchronousTest.prototype.testSave = function(queue) {
  queue.call('Saving user', function(callbacks) {
    var user = new User('Luna');
    user.save(callbacks.add(function(err) {
       if (err) throw err;
       // Run some asserts
    }));
  }); 
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM