2014-11-06 70 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); 
}