最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - mocha with nodejs assert hangstimeouts for assert(false) instead of error - Stack Overflow

programmeradmin0浏览0评论

I have this kind of a mocha test:

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

The problem is, whenever I do assert(false), the test hangs until the timeout, instead of giving an assertion error, why?

Edit:

For example if I have these two tests

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

The first one, gives the assertion error as expected, the second one, logs here, and hangs at assert(false) so after is never logged. It has something to do with articles being a stream and the assertion is within a pull callback, this is from the highland.js API.

Solved Edit:

So according to Paul I fixed the problem with this code:

    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:

I've produced a simplified version of the problem:

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

I see your version does indeed work @Louis, but if you involve promises into the mix, mocha can't handle the problem, so it will hang in this example. Also try commenting out the assert false and see it passes.

So Louis I hope I got your attention, could you explain the problem, and try catch looks ugly indeed and I hope you find a reasonable solution to this.

I have this kind of a mocha test:

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

The problem is, whenever I do assert(false), the test hangs until the timeout, instead of giving an assertion error, why?

Edit:

For example if I have these two tests

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

The first one, gives the assertion error as expected, the second one, logs here, and hangs at assert(false) so after is never logged. It has something to do with articles being a stream and the assertion is within a pull callback, this is from the highland.js API.

Solved Edit:

So according to Paul I fixed the problem with this code:

    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:

I've produced a simplified version of the problem:

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

I see your version does indeed work @Louis, but if you involve promises into the mix, mocha can't handle the problem, so it will hang in this example. Also try commenting out the assert false and see it passes.

So Louis I hope I got your attention, could you explain the problem, and try catch looks ugly indeed and I hope you find a reasonable solution to this.

Share Improve this question edited Nov 8, 2014 at 1:19 user3995789 asked Nov 6, 2014 at 1:38 user3995789user3995789 3,4601 gold badge20 silver badges35 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 13

Because that's what you're telling it you want to do, when you add the 'done' callback.

The way to actually do this test is to call return done(err) if the assertion would fail, where err is any string or error object you want reported.

First, when your assertion fails, the program throws an exception and never reaches done(), which is why you're not seeing done get called. This is how assertions are supposed to work, however since you're in an async test, the result is that the callback never fires, which is why you hit the timeout.

Second, as my original answer said err is any error you want to send out from the test. It can be a string error message or a full-on Error object subclass. You create it and then pass it to done() to indicate the test failed.

The better way to structure your code in an asynchronous test is to use your tests as simple booleans, rather than as assertions. If you really want to use assert, then wrap it in a try..catch. Here's a couple examples:

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

Finally, if you really want to assert, then you can:

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

I'm calling return done(err) rather than done(err) because it stops the rest of the code from executing, which is normally what you want.

For anyone with same issue: You should make sure that done() gets called even after an assert fails, like in the following code:

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

When I use Highland.js with a super simple test, Mocha catches the failing assert without any problem:

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

This suggests that the problem in your example is not Mocha, nor Highland.js. If the articleLinkStream object (or articleSream; it seems to change from snippet to snippet) is custom code then maybe that code is buggy and actually swallows exceptions rather than let them move up the stack.

发布评论

评论列表(0)

  1. 暂无评论