3

I have Node tests with this before function:

before((done) => {
  app.startServer()
    .catch((err) => {
      done(err);
  });
});

I'm now trying to write an after function which will stop the server.

I had hoped this could be:

after(() => {
  app.stopServer(apiAddress)
    .catch((err) => {
      done(err);
    })
});

but that doesn't work.

These are my express.js functions:

function startServer() {
  return new Promise((resolve, reject) => {
    app.listen(PORT, (err) => {
      if (err) reject(err);
      log.info(`Server listening on port ${PORT}`);
      resolve();
    });
  });
}

function stopServer(url) {
  return new Promise((resolve, reject) => {
    //const server = app.listen(url);
    app.close(url, (err) => {
      if (err) reject(err);
      log.info(`Server closed on ${url}`);
      resolve();
    });
  });
}

How do I stop my express server in an after function?

runnerpaul
  • 5,942
  • 8
  • 49
  • 118

2 Answers2

1

We use ‘supertest’ npm package for testing Express.js applications. Try that nice thing. https://www.npmjs.com/package/supertest

Bogdan Surai
  • 1,197
  • 14
  • 16
1

According to this stack overflow question and looking at express documentation.

app.listen

The app.listen() method returns an http.Server object and (for HTTP) is a convenience method for the following:


The close method you are calling is the Http.close method which is defined like :

server.close([callback])

So your function should look like :

function stopServer(url) {
  return new Promise((resolve, reject) => {
    app.close((err) => {
      if (err) reject(err);

      log.info(`Server closed on ${url}`);

      resolve();
    });
  });
}

Also, you have to know that the close function will hang until all connections are closed.

Have a look at this SO question



NOTE :

You can use Util.promisify to simplify the syntax

function startServer() {
  return Util.promisify(app.listen)(PORT);
}

function stopServer(url) {
  return Util.promisify(app.close)();
}

before((done) => {
  app.startServer()
    .then(() => done)
    .catch(done);
});

after(() => {
  app.stopServer()
    .then(() => done)
    .catch(done);
});
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • Thanks. I placed that in a describe block. When the next describe block runs this error is thrown in the before function: `Uncaught Error: listen EADDRINUSE: address already in use :::1337` – runnerpaul May 23 '19 at 09:55
  • I think that an old node.js is running, so the address is already taken. Kill the processes then it will work. You can identify the processes using `htop` or a command like `ps -aux | grep node`. Or `lsof -t -i:1337` so to kill it `kill -9 $(sudo lsof -t -i:1337)` – Orelsanpls May 23 '19 at 09:57
  • I already tried `lsof -t -i:1337` with no joy. Is there some possible async issue between describe blocks? – runnerpaul May 23 '19 at 10:23
  • I don't think so, before will execute first and then fail – Orelsanpls May 23 '19 at 11:28