mocha с NodeJS assert зависает / таймауты для assert (false) вместо ошибки

у меня есть такой тест мокко:

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

первый, дает ошибку утверждения, как и ожидалось, второй, logs here, и зависает на assert(false) так after никогда не регистрируется. Это как-то связано с articles будучи потоком, и утверждение находится в пределах pull обратный вызов, это из Хайленд.С. 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 действительно выглядит некрасиво и я надеюсь, что вы найдете разумное решение этого.

3 ответов


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

способ на самом деле сделать этот тест-позвонить return done(err) если утверждение потерпит неудачу, где err-это любая строка или объект ошибки, о котором вы хотите сообщить.

во-первых, когда ваше утверждение не удается, программа выдает исключение, и никогда не достигает done(), именно поэтому вы не видите, что сделано. Вот как должны работать утверждения, однако, поскольку вы находитесь в асинхронном режиме тест, результат заключается в том, что обратный вызов никогда не срабатывает, поэтому вы нажимаете тайм-аут.

во-вторых, как сказал мой первоначальный ответ err ошибка, которую вы хотите отправить из теста. Это может быть строковое сообщение об ошибке или подкласс объекта full-on 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) потому что он останавливает выполнение остальной части кода, что обычно является тем, что вы хотите.


когда я использую 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();
        });
    });
});

это говорит о том, что проблема в вашем примере не Мокко, ни Хайленд.js. Если


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

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