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

Viewed 1961

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?

3 Answers

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

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.

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.

Related