Search code examples
node.jsasynchronousmocha.jssupertest

.end() function not entered when using async


I am using supertest with async to test some websites. When I execute the test with mocha, the end function is not entered. I added some logging to the end function but it isn't printed. When I remove the async.each, the end function is entered because I see the logging. Any idea what seems to be wrong? Is supertest not compatible with async?

Here is my code:

describe('Era', function() {
it('Does era run?', function(done) {
    async.each(config.url.era, function(url) {
        console.log('Opening connection to ' + url);
        request(url).get('/rest/status').expect(200).end(function(err, res) {
            console.log(err);
            if(err) return done(err);
            console.log('Time to assert some stuff');
            assert.equal(res.text.indexOf('up') > -1, 'Node ' + url + ' failed with status ' + res.statusCode);
        });
    });
    done();
});

Solution

  • async.each() is expecting a callback for each iteration to continue on. In addition, an optional callback at the end of async.each() can be used to call done(). Here is the revised code:

    describe('Era', function() {
        it('Does era run?', function(done) {
            async.each(config.url.era, function(url, eachCb) {
                console.log('Opening connection to ' + url);
                request(url).get('/rest/status').expect(200).end(function(err, res) {
                    console.log(err);
                    if (err) return eachCb(err);  // terminate the loop
                    console.log('Time to assert some stuff');
                    assert.equal(res.text.indexOf('up') > -1, 'Node ' + url + ' failed with status ' + res.statusCode);
                    eachCb(null);  // continue with the next iteration
                });
            }, function(err) {
                if (err) {
                    return done(err);
                }
                done();
                // the above 2 statements can be simplify for just
                // done(err);  // err is an error or null
            });
        });
    });
    

    or above code can be simplified for just this:

    describe('Era', function() {
        it('Does era run?', function(done) {
            async.each(config.url.era, function(url, eachCb) {
                console.log('Opening connection to ' + url);
                request(url).get('/rest/status').expect(200).end(function(err, res) {
                    console.log(err);
                    if (err) return eachCb(err); // terminate the loop
                    console.log('Time to assert some stuff');
                    assert.equal(res.text.indexOf('up') > -1, 'Node ' + url + ' failed with status ' + res.statusCode);
                    eachCb(null);  // continue with the next iteration
                });
            }, done);  // async.each() will call done() with err or null as argument
        });
    });