2014-11-06 42 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), тест не вешает до истечения времени ожидания, а не давать ошибку утверждения, почему?

Edit:

Например, если у меня есть эти два теста

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.

Решено Редактировать:

Так, по словам Павла I решена проблема с этим кодом:

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

Потому что это то, что вы говорите, что хотите сделать, когда вы добавляете обратный вызов «done».

Способ на самом деле выполнить этот тест - вызвать 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

Я написал Мокко код более двух лет тоже, и * * Как правило, вам не нужно ломать исключения, как вы показываете в своем ответе здесь. ** Очень может быть, что 'highland.js' является глотательным исключением или что он имеет некоторую особенность в отношении того, как он обрабатывает исключения в своих обратных вызовах. Но, как правило, Mocha вполне способен обнаруживать исключения, будь то синхронные или асинхронные. Просто запустите 'it (« test », function (done) {setTimeout (function() {throw new Error();}, 100);});' ('done' не вызывается, и это не ошибка.)' Mocha обнаружит исключение без каких-либо проблем. – Louis

+0

@ Louis, вы имеете в виду проглатывание, как описано здесь https://github.com/caolan/highland/issues/121, как вы думаете, это может быть проблемой? – user3995789

+0

@ user3995789 Да, я думаю, это проблема. Я пробовал ваш последний фрагмент с помощью RSVP (другая библиотека обещаний) и получаю те же результаты, что и с Q. Я также пытался использовать «.errors» Хайленда («звонок, но я ничего не получил». – Louis

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

см. ** Редактировать2 ** пожалуйста. – user3995789

0

Для тех, кто с таким же вопросом: Вы должны убедиться, что done() вызывается даже после того, как утверждают не удается, как в следующем коде:

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