摩卡与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() )
第一个,如预期的那样给出断言错误,第二个here
logging,并挂在assert(false)
after
所以从不logging。 它与articles
是一个stream是有关系的,断言是在一个pull
callback中,这是来自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); }