'Jest testing multiple test file port 3000 already in use
I'm creating a testing for my express app. The project has multiple test files. In each module the server instance is required at beforeEach() method and closed at afterEach() method. but after testing one or two of the modules it'll raise address already in use and jest won't terminate.
beforeEach(() => {
server = require('./../../../bin/www')});
afterEach(async() => {
server.close();
/**
* database cleanup logic goes here.
*/
});
I want jest to terminate after all the test suites are completed.
Solution 1:[1]
I had this issue, and seem to have solved it by setting jest to only use one worker. I think the issue was caused by more than one instance of the server running with the same port, thereby causing the clash.
This is the line from my npm package.json file. The --maxWorkers=1
seems to have done the trick (https://jestjs.io/docs/en/cli#maxworkers-num-string).
"scripts": {
"test": "jest --forceExit --detectOpenHandles --watchAll --maxWorkers=1"
},
Solution 2:[2]
Just runs test suites in parallel by default. However, the machine that the tests are running on only has a single port 3000 (or port 4000, etc.)
This means that if you tell your app to listen on a port, and then start multiple concurrent processes, there will be a port collision and Jest will exit with EADDRINUSE - port already in use
.
Like some people already mentioned, you can solve the issue by running your tests in sequence with --runInBand
. However, you will lose out on the performance benefits of parallelization.
There is another way... do not explicitly listen on a port when running tests.
if (process.env.NODE_ENV !== 'test') {
app.listen(port, () => console.log(`Listening on port ${port}`)
}
Now, when you feed your app to supertest, it will run your app on port 0 since it's not already running on a port.
const app = require('../app')
const request = require('supertest')
it('gets todos', async () => {
const response = await request(app).get('/todos')
expect(response.body.length).toEqual(3)
}
What exactly is port 0 you ask? That is how you tell Unix machines...
Choose the first randomly available port that you find.
Now that each test suite is running on a randomly available port, there is no longer a risk of port collisions which means we've solved the EADDRINUSE - port already in use
error and we can continue running tests in parallel.
Solution 3:[3]
the very basic thing to do is to put your app.listen() inside some other file , other than your file that consists all the routes . for example : index.js
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.json());
const students = ["Elie", "Matt", "Joel", "Michael"];
app.get("/", (req, res) => {
return res.json(students);
});
module.exports = app;
and server.js
const app = require("./index");
app.listen(3000, () => console.log("server starting on port 3000!"));
In this way Jest will not be reading app.listen() at all . cheers !
Solution 4:[4]
I'm using, node express server 4.16.2. If you're using a different version this may not apply to you.
In your describe block when you're closing the server, await
for it.
describe('auth midleware', () => {
// loading the server
beforeEach(() => {>
server = require('../../../index')
});
// closing the server
afterEach(async () => {
await server.close();
});
// the tests will go here
});
Also after you do this, run your node application in the command line.
node index.js
Check your package.json, how your script test tag is named. Mine is test.
{ ...
"scripts": {
"test": "jest --verbose --coverage --forceExit --watchAll --maxWorkers=1"
}
...
}
After that run your test again.
npm test
Solution 5:[5]
There is also an option --runInBand to run tests one by one.
Solution 6:[6]
server = require('./../../../bin/www')});
afterEach(async() => {
await server.close();
you just have make it await to close the server properly.
Solution 7:[7]
I had the same issue, it turns out the last test case was not allowing jest close properly before moving to the next test suite, so I added
it('should blah blah', asyn(done) => {
test code...
done()
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | John Forbes |
Solution 2 | J. Munson |
Solution 3 | VicCoder0659 |
Solution 4 | |
Solution 5 | Dmitry Skryabin |
Solution 6 | Chamath Kavindya |
Solution 7 | Simson |