我有这种摩卡测试:
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)
时,测试会一直持续到超时,而不是给出断言错误,为什么?
修改
例如,如果我有这两个测试
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
,并挂起assert(false)
,因此永远不会记录after
。它与articles
是一个流有关,而断言在pull
回调中,这来自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)
)
EDIT2 :
我已经制作了问题的简化版本:
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,但如果你将promises包含在混合中,mocha就无法解决问题,所以它会在这个例子中挂起。同时尝试评论assert false
并看到它通过。
所以路易斯我希望我能引起你的注意,你能否解释一下这个问题,try catch
看起来确实很难看,我希望你能找到一个合理的解决办法。
答案 0 :(得分:8)
因为这是你想要做的,当你添加'完成'回调时。
实际执行此测试的方法是在断言失败时调用return done(err)
,其中err是您要报告的任何字符串或错误对象。
首先,当你的断言失败时,程序抛出异常并且永远不会到达done()
,这就是为什么你没有看到完成被调用的原因。这就是断言应该如何工作,但是由于你处于异步测试中,结果是回调永远不会触发,这就是你达到超时的原因。
其次,正如我原来的回答所说,err
是您想要从测试中发出的任何错误。它可以是字符串错误消息或完整的Error对象子类。您创建它然后将其传递给done()
以指示测试失败。
在异步测试中构造代码的更好方法是将测试用作简单的布尔值,而不是断言。如果你真的想使用assert,那么将它包装在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)
,因为它会停止执行其余代码,这通常是您想要的。
答案 1 :(得分:1)
对于有相同问题的任何人:您应该确保即使在断言失败后也会调用done()
,如下面的代码所示:
try {
// your asserts go here
done();
} catch (e) {
done(e);
}
答案 2 :(得分:0)
当我使用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();
});
});
});
这表明你的例子中的问题不是Mocha,也不是Highland.js。如果articleLinkStream
对象(或articleSream
;它似乎从代码段改为代码段)是自定义代码,那么可能代码是错误的,实际上是吞下异常,而不是让它们向上移动。