2014-11-06 12 views
6

mam ten rodzaj testu mokka:mokka z nodejs dochodzić zawiesza/limity czasu dla assert (false) zamiast błędu

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() 
     ) 

Problem jest, gdy mam assert(false) test wisi aż do czasu oczekiwania, zamiast podawać błąd potwierdzenia, dlaczego?

Edit:

Na przykład jeśli mam te dwa testy

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() 
     ) 

Pierwszy z nich, daje błąd twierdzenie, zgodnie z oczekiwaniami, drugi, dzienniki here i wisi na assert(false) tak after nigdy nie jest zalogowany. Ma to związek z tym, że articles jest strumieniem, a asercja jest wywoływana przez wywołanie zwrotne pull, to jest z highland.js API.

rozwiązać Edit:

Więc według Pawła Naprawiłem problem z tym kodem:

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:

Mam produkowanego uproszczoną wersję problemu :

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() 
     ) 

Widzę, że twoja wersja rzeczywiście działa na zasadzie @Louis, ale jeśli zaangażujesz się w obietnicę, mocha nie poradzi sobie z problemem, więc zawiesi się w tym przykładzie. Spróbuj również komentować numer assert false i zobacz, jak przechodzi.

Więc Louis Mam nadzieję, że zwróciłem twoją uwagę, czy mógłbyś wyjaśnić problem, a try catch wygląda naprawdę brzydko i mam nadzieję, że znajdziesz rozsądne rozwiązanie tego problemu.

Odpowiedz

7

Bo właśnie to mówisz, że chcesz zrobić, po dodaniu "zakończone" oddzwanianie.

Sposób na wykonanie tego testu polega na wywołaniu return done(err), jeśli asercja nie powiedzie się, gdzie err to dowolny ciąg lub obiekt błędu, który chcesz zgłosić.

Po pierwsze, gdy twoje twierdzenie nie powiedzie się, program zgłasza wyjątek i nigdy nie dociera do done(), dlatego nie widzisz, aby zostało wykonane. Tak właśnie powinno działać twierdzenie, jednak ponieważ jesteś w teście asynchronicznym, wynikiem jest, że wywołanie zwrotne nigdy nie jest uruchamiane, dlatego właśnie trafiłeś w limit czasu.

Po drugie, moja oryginalna odpowiedź brzmi: err to błąd, który chcesz wysłać z testu. Może to być komunikat o błędzie ciąg lub pełna podklasa obiektu błędu. Tworzysz go, a następnie przekazujesz do done(), aby wskazać, że test się nie powiódł.

Lepszym sposobem na ustrukturowanie kodu w teście asynchronicznym jest użycie testów jako prostych wartości logicznych, a nie jako asercji. Jeśli naprawdę chcesz użyć aserta, zapakuj go w try..catch.Oto kilka przykładów:

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!'); 

Wreszcie, jeśli naprawdę chcesz assert, wówczas można:

try{ 
    assert(!err); 
}catch(e){ 
    return done(e); 
} 

Dzwonię return done(err) zamiast done(err) ponieważ zatrzymuje resztę kodu z wykonaniem , co zwykle jest tym, czego potrzebujesz.

+1

Pisałem kod Mocha od ponad dwóch lat także i * * generalnie nie musisz wychwytywać wyjątków takich jak w Twojej odpowiedzi tutaj. ** Może się zdarzyć, że 'highland.js' przełknie wyjątek lub że ma pewne cechy szczególne dotyczące sposobu obsługi wyjątków w swoich wywołaniach zwrotnych. Generalnie jednak Mocha potrafi wykrywać wyjątki, czy to synchroniczne, czy asynchroniczne. Po prostu uruchom 'to (" test ", function (done) {setTimeout (function() {throw new Error();}, 100);});' ('done' nie jest wywoływane i nie jest to błąd). Mocha wykryje wyjątek bez żadnego problemu. – Louis

+0

@ Louis, masz na myśli połykanie jak opisano tutaj https://github.com/caolan/highland/issues/121, myślisz, że to może być problem? – user3995789

+0

@ user3995789 Tak, myślę, że to jest problem. Próbowałem twój najnowszy fragment z RSVP (inną biblioteką obietnicy) i uzyskałem takie same wyniki, jak w przypadku Q. Próbowałem też użyć '.romors (' call, ale nic nie dostałem z tego.) – Louis

0

Gdy używam Highland.js z super prosty test, Mocha uszkodzonej łapie bez problemu stwierdzić:

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(); 
     }); 
    }); 
}); 

To sugeruje, że problem w swoim przykładzie nie jest Mocha, ani Highland.js. Jeśli obiekt articleLinkStream (lub articleSream, wydaje się, że zmienia się z fragmentu kodu do fragmentu kodu) jest niestandardowym kodem, to może ten kod jest błędny i faktycznie przechwytuje wyjątki, a nie pozwala im przesuwać się w górę stosu.

+0

zobacz ** Edit2 ** proszę. – user3995789

0

Dla każdego z samej kwestii: Należy upewnić się, że done() pobiera nazywane nawet po awarii assert, jak w poniższym kodzie:

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