有什么方法可以让柴使用异步Mocha测试吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (32)

我使用Browser Runner在Mocha中运行一些异步测试,并试图使用Chai的期望样式断言:

window.expect = chai.expect;
describe('my test', function() {
  it('should do something', function (done) {
    setTimeout(function () {
      expect(true).to.equal(false);
    }, 100);
  }
}

这不会给我正常的失败的断言信息,而是我得到:

Error: the string "Uncaught AssertionError: expected true to equal false" was thrown, throw an Error :)
    at Runner.fail (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3475:11)
    at Runner.uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3748:8)
    at uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3778:10)

所以它显然捕捉到错误,只是没有正确显示。有没有什么想法如何做到这一点?

提问于
用户回答回答于

你的异步测试会在失败的情况下生成一个异常,由于异常被抛出范围之外而expect()无法捕获it()异常。

你看到显示的捕获异常是process.on('uncaughtException')在节点下使用或window.onerror()在浏览器中使用捕获的。

为了解决这个问题,需要捕获异常函数中的异常setTimeout(),以便done()将异常作为第一个参数进行调用。你还需要done()使用无参数调用来指示成功,否则mocha会报告超时错误,因为你的测试函数永远不会发出已完成的信号:

window.expect = chai.expect;

describe( 'my test', function() {
  it( 'should do something', function ( done ) {
    // done() is provided by it() to indicate asynchronous completion
    // call done() with no parameter to indicate that it() is done() and successful
    // or with an error to indicate that it() failed
    setTimeout( function () {
      // Called from the event loop, not it()
      // So only the event loop could capture uncaught exceptions from here
      try {
        expect( true ).to.equal( false );
        done(); // success: call done with no parameter to indicate that it() is done()
      } catch( e ) {
        done( e ); // failure: call done with an error Object to indicate that it() failed
      }
    }, 100 );
    // returns immediately after setting timeout
    // so it() can no longer catch exception happening asynchronously
  }
}

在你所有的测试案例中这样做是烦人的,而不是干的,所以你可能想提供一个函数来为你做这件事。我们来调用这个函数check()

function check( done, f ) {
  try {
    f();
    done();
  } catch( e ) {
    done( e );
  }
}

现在check()可以按照以下方式重写异步测试:

window.expect = chai.expect;

describe( 'my test', function() {
  it( 'should do something', function( done ) {
    setTimeout( function () {
      check( done, function() {
        expect( true ).to.equal( false );
      } );
    }, 100 );
  }
}
用户回答回答于

如果你喜欢承诺,试试Chai as Promised + Q,它允许这样的事情:

doSomethingAsync().should.eventually.equal("foo").notify(done);

扫码关注云+社区