mocha with nodejs assert hangs/timeouts for assert(false) instead of error

我的未来我决定 提交于 2019-12-19 17:46:48

问题


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.


回答1:


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.




回答2:


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



回答3:


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.



来源:https://stackoverflow.com/questions/26770345/mocha-with-nodejs-assert-hangs-timeouts-for-assertfalse-instead-of-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!