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

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

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

    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 обратный вызов, это из API highland.js.

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

Итак, по словам Павла, я исправил проблему с этим кодом:

    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, но если вы включите обещания в микс, mocha не сможет решить проблему, поэтому в этом примере она зависнет. Также попробуйте закомментировать assert false и увидеть, как это проходит.

Итак, Луи, надеюсь, я привлек ваше внимание, не могли бы вы объяснить проблему, и try catch выглядит действительно некрасиво, и я надеюсь, что вы найдете разумное решение для этого.

3 ответа

Решение

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

Способ сделать этот тест, чтобы позвонить 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) потому что он останавливает выполнение остальной части кода, что, как правило, то, что вы хотите.

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

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

Когда я использую Highland.js с очень простым тестом, Mocha ловит ошибочное утверждение без проблем:

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

Это говорит о том, что проблема в вашем примере не в Mocha или Highland.js. Если articleLinkStream объект (или articleSream; кажется, что он изменяется от сниппета к сниппету) - это пользовательский код, тогда, возможно, этот код содержит ошибки и фактически проглатывает исключения, а не позволяет им перемещаться вверх по стеку.

Другие вопросы по тегам