'How to fix "listen EADDRINUSE: address already in use :::3000" error in Integration test?

I am trying to test my simple endpoint using jest and superTest in my TypeScript project but I am getting listen EADDRINUSE: address already in use :::3000 error.

  • I have a app.ts for express work. This is the one I am importing in my test file.
  • I have a server.ts file which starts the server. I am NOT using this in my test.

I am reading some similar questions on stackoverflow where people are suggesting killing the process. My issue is only with my Integration Test. It works fine if I test with Postman.

Question(s):

  • Should I stop the server in afterEach? I am not 100% sure if this a valid approach.

Here is the code:

app.ts

import 'reflect-metadata';
import * as express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import app from './server';
import routes from './routes/routes';
import errorHandler from './utils/errorHandler';
import LoggerService from './services/logger.service';

async function bootstrap() {
  app.disable('x-powered-by'); 
  app.use(cors());
  app.use(helmet());
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));
  routes(app);
  /**
 * Configure error handler
 */
  errorHandler(app);
}

// Need for testing purpose
export default app;

bootstrap()
  .then(() => {
    new LoggerService().logger.info('Server is up');
  })
  .catch((error) => {
    new LoggerService().logger.error(`Unknown error. ${error.message}`);
  });

server.ts

import * as dotenv from 'dotenv';
import express from 'express';
import LoggerService from './services/logger.service';

dotenv.config();

const server = express();

/**
 * App Variables
 */
if (!process.env.PORT) {
  process.exit(1);
}

/**
 * Setup listener port
 */
const PORT: string | number = process.env.PORT || 3000;
server.listen(PORT, () => {
  new LoggerService().logger.info(`Listening on port ${PORT}`);
});

export default server;

route.ts

import { Application } from 'express';
import container from '../ioc.container';
import HealthController from '../controllers/health.controller';

export default function RouteManager(application: Application) {
  const healthController = container.get<HealthController>(HealthController);

  application.get('/healthStatus', healthController.healthCheck.bind(healthController));
}

some.spec.ts

import { mockHealthCheck } from '../mockData/health.mockData';
import app from '../app';
import request from 'supertest';

describe('GET /healthStatus API Tests', () => {

  it('Receives 200 on successful call', async () => {
    const result = await request(app).get('/healthStatus');
    expect(result.statusCode).toEqual(200);
    expect(result.body.description).toEqual(mockHealthCheck.description);
    expect(result.body.status).toEqual(mockHealthCheck.status);
  });

  it('Receives 404 - Not Found on unsuccessful call', async () => {
    const result = await request(app).get('/invalidEndPoint');
    expect(result.statusCode).toEqual(401);
  });

});



Solution 1:[1]

I can fix this issue if I make following changes in my app.ts and server.ts files. Remaininig files stays same (route.ts and some.spec.ts).

app.ts

/**
 * Required External Modules
 */
import 'reflect-metadata';
import * as dotenv from 'dotenv';
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import routes from './routes/routes';

dotenv.config();

const app = express();

/**
 *  App Configuration
 */
app.use(helmet()); 
app.use(cors());
app.use(express.json());
app.disable('x-powered-by'); 
routes(app);

export default app;

server.ts

import app from './app';
import LoggerService from './services/logger.service';

/**
 * App Variables
 */
if (!process.env.PORT) {
  process.exit(1);
}

const PORT: number = parseInt(process.env.PORT as string, 10);
app.listen(PORT, () => {
  new LoggerService().logger.info(`Listening on port ${PORT}`);
});

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 GThree