4

I'm currently facing a bug that I can't resolve and I have been struggling for some hours.
I'm using the following versions:
Node: 8.11.3
Express: 4.16.3
Jest: 22.2.2
Mongoose: 5.2.3

I'm trying to do some integration tests with jest and I have 2 files with tests.
In each file I wrote the following:
// Create the server before each test.
beforeEach(() => {
    server = require('../../index');
});

// Close the server after each test.
afterEach(async () => {
    if (server) {
        server.close();
    }
});

In index.js I have the following (This is not all the code, but the relevant code for the bug):

// Listen to the server.
const port = config.PORT || process.env.PORT || 3000;
module.exports = app.listen(port, () => {
   winston.info(`Listening to port ${port}...`);
});

When I run npm test I get this exception all the time:

**listen EADDRINUSE :::3000**

  10 | // Listen to the server
  11 | const port = config.PORT || process.env.PORT || 3000;
> 12 | module.exports = app.listen(port, () => {
  13 |     winston.info(`Listening to port ${port}...`);
  14 | });
  15 |

I tried several ways to solve this by adding async await to beforeEach and for afterEach and tried also to put the sever.close in afterAll and in beforeAll but still got the same error.

Then, I tried to solve by doing this:
How Do I Shut Down My Express Server Gracefully When Its Process Is Killed?

But again, with no luck.
Finally, when I wrote all the tests in 1 file, it works without this error. Does anybody know how to solve this? I don't want to write all my integration tests in 1 file..
Thanks!

Or Assayag
  • 5,662
  • 13
  • 57
  • 93

4 Answers4

11

Try setting the --runInBand flag, this will run your tests sequentially.

https://jestjs.io/docs/en/cli#runinband

In package.json scripts:

"scripts": {
    ...
    "test": "jest --watchAll --verbose --runInBand",
    ...
}

[UPDATE] On further investigation, while you can use --runInBand to run your tests sequentially, another option is to await the server.close() since it returns a promise. As such, in your afterEach:

...
await server.close();
...

[UPDATE] I believe a better way to solve this issue is to separate out the index.js file into an index.js and a server.js file. This enables you to pull your index.js file into your tests without .listen:

// index.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.status(200).send({ hello: "world!" });
});

module.exports = app;

Then in a separate server.js file:

const server = require("./index");

const PORT = process.env.PORT || 3001;

server.listen(PORT, () => {
  console.log(`App running on: ${PORT}`);
});

module.exports = server;

When running your app, you run: node server.js.

This then enables you to test your routes by pulling your index.js file into your test as follows:

// test.js
const request = require("supertest");
const server = require("./index");

describe("GET /", () => {

  test("should return status 200", async () => {
    const res = await request(server).get("/");
    expect(res.status).toBe(200);
  });


});

  • 2
    runInBand works, but is a bit of a band aid. await server.close() hasn't worked for me, and looking at the code above I think I've got the same problem (codingwithmosh?) – NickW Dec 10 '18 at 18:29
  • Yes to both: 1) This example is from "Coding with Mosh" and 2) The solution is to use "await server.close()"—what happens otherwise is that the next test is run before the server has actually closed. Thank you @Nicholas Pretorius! – Jérémie Dec 15 '18 at 04:17
  • 1
    you saved my life, spent like 3 hours to solve it, yeah me too "Codding with Mosh"!!! – Vladislav Guleaev Feb 16 '19 at 22:16
3

I am following the same course and had the same issue. --runInBand solved it for me.

Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
CriptoGirl
  • 51
  • 2
  • 3
    Actually, Mosh covers this in later section of his course '5- Testing the Authorization'. His solution is to use to await server.close(); – CriptoGirl Mar 07 '19 at 18:01
2

The issue here is requiring server file multiple times. You shouldn't require server file like that. Each time you do that, an instance starts, in your first test file an instance of server already started, while requiring server for your second file, it tries to start another instance, but then your server is already running on 3000 and hence the error.

Sachin S
  • 186
  • 8
  • So what is the solution? – Or Assayag Jul 18 '18 at 04:37
  • 1
    The solution I recommend is to create a base file that requires the server and all your test files into it, and from there, your test files can access server object and the server gets required only once. – Sachin S Jul 18 '18 at 04:42
  • Sounds great, do you have any reference that i cant use to see? – Or Assayag Jul 18 '18 at 06:58
  • 2
    funny that this has been down voted - i think this might be the best solution. I'm going to try and implement it. did you ever come up with an answer OrAssayag? – NickW Dec 10 '18 at 18:29
1

I think your port 3000 is busy somewhere else Or maybe this app is running on somewhere else in the terminal, Check it and close all the instances of this app.

Or

Try to use below code:

// Listen to the server
  11 | const port = config.PORT || process.env.PORT || 3001; // CHANGE POST 3000-> 3001
> 12 | module.exports = app.listen(port, () => {
  13 |     winston.info(`Listening to port ${port}...`);
  14 | });
Shubham Verma
  • 8,783
  • 6
  • 58
  • 79