2014-11-06 53 views
6

我有这样的摩卡测试:摩卡用的NodeJS断言挂起/超时的断言(假),而不是错误

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工作,但是如果你涉及承诺,摩卡不能处理这个问题,所以它会在这个例子中挂起。也可以尝试注释掉assert false,看看它通过了。

所以路易斯我希望我能引起你的注意,你能否解释这个问题,try catch的确看起来很丑,我希望你找到合理的解决方案。

回答

7

因为这是你想做的事,当你添加的“完成”回调你告诉它什么。

实际进行此测试的方法是,如果断言失败,则调用return done(err),其中err是要报告的任何字符串或错误对象。

首先,当你的断言失败,程序会抛出异常,并不会达到done(),这就是为什么你没有看到进行调用。这就是断言应该如何工作,但是因为你在异步测试中,结果是回调从不会触发,这就是为什么你打到了超时。

其次,我原来的答复说err是你想从测试发出任何错误。它可以是一个字符串错误消息或一个完整的Error对象子类。您创建它,然后将其传递到done()以指示测试失败。

更好的方式来构建异步测试你的代码是用你的测试一样简单布尔值,而不是断言。如果你真的想使用断言,然后将其包装在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

我写摩卡代码两年多也和* *一般来说,您不需要像在回答中显示的那样捕获异常。**很可能''highland.js'正在吞噬异常,或者它在处理回调中的异常方面有一些特殊性。但一般来说,Mocha非常有能力检测异常,无论是同步还是异步。只要运行'it(“test”,function(done){setTimeout(function(){throw new Error();},100);});'('done'不被调用,这不是错误。摩卡将检测到没有任何问题的例外。 – Louis 2014-11-07 23:17:05

+0

@Louis,你的意思是吞咽像这里描述https://github.com/caolan/highland/issues/121,你认为这可能是问题? – user3995789 2014-11-08 01:22:51

+0

@ user3995789是的,我认为这是问题所在。我已经尝试过使用RSVP(另一个承诺库)的最新代码片段,并获得与Q相同的结果。我也尝试使用Highland的'.errors('call但我没有得到任何东西。 – Louis 2014-11-08 12:00:48

0

当我使用Highland.js一个超级简单的测试,摩卡捕获失败的断言,没有任何问题:

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;它似乎从片段更改为片段)是自定义代码,那么也许该代码是错误的,并且实际吞下异常,而不是让它们向上移动堆栈。

+0

请参阅** Edit2 **。 – user3995789 2014-11-08 01:20:29

0

对于同一个问题的人:你应该确保done()得到下面的代码称为断言失败后,也一样:

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