摩卡与nodejs断言悬挂/超时断言(错误),而不是错误

我有这种摩卡testing:

describe 'sabah', → beforeEach → @sabahStrategy = _.filter(@strats, { name: 'sabah2' })[0] .strat it 'article list should be populated', (done) → @timeout 10000 strat = new @sabahStrategy() articles = strat.getArticleStream('barlas') articles.take(2).toArray( (result)→ _.each(result, (articleList) → // I make the assertions here // assert(false) assert(articleList.length > 1) ) done() ) 

问题是,每当我assert(false) ,testing挂起,直到超时,而不是给一个断言错误,为什么?

编辑:

例如,如果我有这两个testing

  it 'assert false', (done) → assert(false) done() it 'article link stream should be populated', (done) → @timeout 20000 articles = @sabahStrategy.articleLinkStream('barlas') articles.pull((err, result)→ console.log('here') assert(false) console.log('after') assert(!err) assert(result.length > 1); _.each(result, (articleList) → assert(articleList.link) ) done() ) 

第一个,如预期的那样给出断言错误,第二个herelogging,并挂在assert(false) after所以从不logging。 它与articles是一个stream是有关系的,断言是在一个pullcallback中,这是来自highland.js API 。

已解决编辑

所以根据保罗,我解决了这个问题的代码:

  it 'article stream should be populated', (done) → @timeout 30000 articles = @sabahStrategy.articleStream('barlas') articles.pull((err, result) → try # assert false properly throws now. assert(false) assert(!err) assert(result.length == 1) assert(result[0].body) assert(result[0].title || result[0].title2) done() catch e done(e) ) 

编辑2

我已经提出了一个简化版本的问题:

 h = require('highland') Q = require('q') describe 'testasynchigh', → beforeEach → @deferred = Q.defer() setTimeout((→ @deferred.resolve(1) ).bind(this), 50) it 'should throw', (done) → s = h(@deferred.promise); s.pull((err, result) → console.log result assert false done() ) 

我看到你的版本确实在@Louis工作,但如果你涉及到承诺,摩卡不能处理这个问题,所以它会挂在这个例子。 另外尝试注释assert false并看到它通过。

所以路易斯,我希望我能引起你的注意,你能解释一下这个问题吗? try catch看上去很丑,我希望你find一个合理的解决办法。

因为这就是你要做的,当你添加“完成”callback。

实际做这个testing的方法是调用return done(err)如果断言失败,其中err是你想要报告的任何string或错误对象。

首先,当你的断言失败时,程序抛出一个exception,永远不会达到done() ,这就是为什么你没有看到完成调用。 这是断言应该如何工作,但是由于你在asynchronoustesting,结果是callback不会触发,这就是为什么你超时。

其次,正如我原来的回答所说, err是你想从testing中发出的任何错误。 它可以是一个string错误消息或一个完整的Error对象的子类。 您创build它,然后将其传递给done()以指示testing失败。

在asynchronoustesting中构build代码的更好方法是将testing用作简单的布尔值,而不是断言。 如果你真的想使用断言,然后包装它try..catch 。 这里有几个例子:

 if(err) return done(err); // in this case, err is defined as part of the parent callback signature that you have in your code already. if(result.length < 1) return done('Result was empty!'); 

最后,如果你真的想assert ,那么你可以:

 try{ assert(!err); }catch(e){ return done(e); } 

我调用return done(err)而不是done(err)因为它阻止了执行代码的其余部分,这通常是你想要的。

当我用一个超级简单的testing来使用Highland.js时,Mocha捕获了失败的断言,没有任何问题:

 var _ = require("highland"); var fs = require("fs"); var assert = require("assert"); describe("test", function () { it("test", function (done) { var s = _([1, 2, 3, 4]); s.pull(function (err, result) { console.log(result); assert(false); done(); }); }); }); 

这表明在你的例子中的问题不是摩卡,也不是Highland.js。 如果articleLinkStream对象(或articleSream ;它似乎从片段更改为片段)是自定义代码,那么也许该代码是越野车,并且实际吞下exception,而不是让他们向上移动堆栈。

对于任何人都有同样的问题:你应该确保done()被调用,即使在断言失败后,就像下面的代码:

 try { // your asserts go here done(); } catch (e) { done(e); }