Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mocha watching fails under npm

I have a very simple Koa application:

var app = module.exports = require("koa")();

app.use(function *(){
    this.body = "Koa says Hi!";
});

var port = process.env.PORT || (process.argv[2] || 3000);
port = (typeof port === "number") ? port : 3000;

app.listen(port);
console.log("Application started. Listening on port:" + port);

that I test with mocha and supertest like this;

var app = require("../");
var request = require("supertest").agent(app.listen());

describe("Our amazing site", function () {

    it("has a nice welcoming message", function (done) {
        request
            .get("/")
            .expect("Koa says Hi!")
            .end(done);
    });
});

I want to watch my files for changes and use the -w flag like this

mocha -u bdd -R min -w

That works fine. I change a file, the test is reexcuted and all is well.

But, very strangely, if I move that command into my package.json file as a script, like this:

"scripts": {
    "watch:test": "mocha -u bdd -R min -w"
},

The first time I run the command it works, when I make a change that is picked up but now the test fails with:

1)  Uncaught error outside test suite:
     Uncaught Error: listen EADDRINUSE :::3000
      at Object.exports._errnoException (util.js:837:11)
      at exports._exceptionWithHostPort (util.js:860:20)
      at Server._listen2 (net.js:1231:14)
      at listen (net.js:1267:10)
      at Server.listen (net.js:1363:5)
      at Application.app.listen (node_modules/koa/lib/application.js:70:24)
      at Object.<anonymous> (index.js:10:5)
      at Object.<anonymous> (test/site.spec.js:1:73)
      at Array.forEach (native)
      at StatWatcher._handle.onchange (fs.js:1285:10)

That error will not go away until I stop mocha and then restart it.

Why does it behave differently when run via npm? What can I do to fix this?

like image 761
Marcus Hammarberg Avatar asked Sep 30 '15 14:09

Marcus Hammarberg


1 Answers

Ok - I found the solution. This has to do with that I'm starting an app twice, when under test. And not closing both.

To start testing with Supertest you construct a request like this: var request = require("supertest").agent(app.listen());. Btw the app.listen() is the same thing as we do in our application.

Since we are watching our files for changes the server never gets close. On the next run of the test it starts again: var request = require("supertest").agent(app.listen()); and the "Address is in use".

The solution is simple: just start listening when you are not running under test. A simple way to do that is by checking for a module parent in your application:

if(!module.parent) {
   app.listen();
}
like image 160
Marcus Hammarberg Avatar answered Nov 04 '22 00:11

Marcus Hammarberg