Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha tests timeout if more than 4 tests are run at once

I've got a node.js + express web server that I'm testing with Mocha. I start the web server within the test harness, and also connect to a mongodb to look for output:

describe("Api", function() {        
    before(function(done) {
        // start server using function exported from another js file
        // connect to mongo db
    });

    after(function(done) {
        // shut down server
        // close mongo connection
    });

    beforeEach(function(done) {
        // empty mongo collection
    });

    describe("Events", function() {    
        it("Test1", ...);
        it("Test2", ...);
        it("Test3", ...);
        it("Test4", ...);
        it("Test5", ...);
    });
});

If Mocha runs more than 4 tests at a time, it times out:

4 passing (2s)
1 failing

1) Api Test5:
   Error: timeout of 2000ms exceeded
    at null.<anonymous> (C:\Users\<username>\AppData\Roaming\npm\node_modules\moch\lib\runnable.js:165:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

If I skip any one of the 5 tests, it passes successfully. The same problem occurs if I reorder the tests (it's always the last one that times out). Splitting the tests into groups also doesn't change things.

From poking at it, the request for the final test is being sent to the web server (using http module), but it's not being received by express. Some of the tests make one request, some more than one. It doesn't affect the outcome which ones I skip. I haven't been able to replicate this behaviour outside mocha.

What on earth is going on?

like image 369
thecoop Avatar asked Oct 02 '22 15:10

thecoop


1 Answers

With Mocha, if you declare a first argument to your (test) functions' callback (usually called done), you must call it, otherwise Mocha will wait until it's called (and eventually time out). If you're not going to need it in a test, don't declare it:

it('test1', function(done) {
  ..
  // 'done' declared, so call it (eventually, usually when some async action is done)
  done();
});

it('test2', function() {
  // not an async test, not declaring 'done', obviously no need to call it
});

And since you're using http, try increasing http.globalAgent.maxSockets (which defaults to 5):

var http = require('http');
http.globalAgent.maxSockets = 100;

(I believe 0 turns it off completely but I haven't tried).

like image 67
robertklep Avatar answered Oct 06 '22 00:10

robertklep