andrzej541
andrzej541

Reputation: 961

Node EADDRINUSE: address already in use :::3000 when testing with jest and supertest

I am trying to test my API endpoints with jest and supertest:

my test routes file:

const app = require('../../index') 
const request = require('supertest')


describe('test app endpoints', ()=>{
    test('index should return 200 code', async (done) =>{
        const response = await request(app).get('/')
        expect(response.statusCode).toBe(200)
        done()
    })

index.js:

const express = require('express')
const bodyParser = require('body-parser')
const app = express()

const port = 3000


app.set('view engine', 'ejs')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.use('/', require('./routes/conversions'))

module.exports = app.listen(port, (err) => {
    if (err) throw err
    console.log(`Server is running on port ${port}`)
})

When I run this test I get error about occupied port:

listen EADDRINUSE: address already in use :::3000

How can I fix that and do not block my port for tests?

Upvotes: 8

Views: 5004

Answers (4)

Aayush Anand
Aayush Anand

Reputation: 55

If you're on linux then you can use ss.

Say for example your port which is already bound to by another application is 3000, then you can use the following command to list all the applications which are currently either bound/ have an open socket listening from the port 3000 :-

ss -ap | grep 3000

You'll be also shown the name of the processes along with their pid.

Take a note of the process id of the process which is no longer needed, and then run a kill -9 PID to get rid of it.

You'll need to get rid of the process which is bound to the port 3000 to be able to launch a new process which binds to it.

Only one process at most can bind itself to a port on a machine.

Upvotes: 0

Albert Vila Calvo
Albert Vila Calvo

Reputation: 15835

You need to avoid calling app.listen() when you run tests. While wrapping app.listen() in an if statement works, you can also organize your code like this:

// app.ts

import express from 'express'
import { router } from './router'

const app = express()

app.use(express.json())
app.use('/api', router)
// more setup here...

export { app }
// index.ts or server.ts

import { app } from './app'

app.listen(3000, () => {
  console.log(`Server running on port 3000`)
})

Then in your tests import app from app.ts, which avoids the EADDRINUSE issue.

This answer adds a bit more info on this.

Upvotes: 3

Avital A.
Avital A.

Reputation: 341

This issue is actually with the way you are running the server in the testing environment. A simple fix for this issue is wrapping app.listen() in a condition to check if the environment is a test environment or not. In a test environment, when running the server through Supertest, you don't need to have the app listen on a network port. So fix this by adding a conditional check to index.js:

if (process.env.NODE_ENV !== 'test') {
    app.listen(port);
}

for more read this

Upvotes: 16

Caleb Denio
Caleb Denio

Reputation: 1685

Something else on your computer is using port 3000; that's all. Just set the port variable to something else; 8080 and 8000 are popular choices.

Upvotes: 0

Related Questions