'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.tsforexpresswork. This is the one I am importing in my test file. - I have a
server.tsfile 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 |
