7

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?

andrzej541
  • 919
  • 1
  • 9
  • 21

3 Answers3

12

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

Avital A.
  • 183
  • 1
  • 9
0

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.

Caleb Denio
  • 1,465
  • 8
  • 15
  • 1
    unfortunately this is not an issue since "lsof -i :3000" returns no other programs running on that port. I belive it's a problem with jest or supertests and they run those ports multiple times. I tried to change my port number to something else and I get the same error but with the new port number. – andrzej541 Mar 22 '20 at 18:44
  • Just to confirm, the code works when you run `node index.js`? – Caleb Denio Mar 22 '20 at 20:44
0

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.

Albert Vila Calvo
  • 15,298
  • 6
  • 62
  • 73