EADDRINUSE :::3000 in jest - jestjs

I know this error means that port 3000 is already in use but I also tried a different port but I am still getting the same errors for some specific tests only.
This is the code of one of those test
describe("GET /", () => {
it("should return all genres", async() => {
await Genre.collection.insertMany([
{name: 'genre1'},
{name: 'genre2'}
]);
const res = await request(server).get('/api/genres');
expect(res.status).toBe(200);
expect(res.body.length).toBe(2);
expect(res.body.some( g => g.name === 'genre1')).toBeTruthy();
expect(res.body.some( g => g.name === 'genre2')).toBeTruthy();
});
});
Any way to solve this error?
listen EADDRINUSE :::3000
10 |
11 | const port = process.env.PORT || 3000;
> 12 | const server = app.listen(port, () => winston.info(`Listening on port ${port}...`));
| ^
13 |
14 | module.exports = server;
15 |
at Function.listen (node_modules/express/lib/application.js:618:24)
at Object.listen (index.js:12:20)
● /api/returns › Should return 400 if customerId is not given
connect ECONNREFUSED 127.0.0.1:62801
This is what i'm getting in the console

I think that the issue is down to not closing the server between test runs in Jest.
If you're using jest --watch to run your tests then it might help to add an afterAll handler?
Example minimal express app:
// app.js
const express = require("express");
const app = express();
// Server port
const HTTP_PORT = 3000;
// Start server
server = app.listen(HTTP_PORT, () => {
//console.log(`Server running on port ${HTTP_PORT}`);
});
// Root endpoint
app.get("/", (req, res, next) => {
res.json({"message":"Ok yah!"})
});
// Default response for any other request
app.use(function(req, res){
res.status(404);
});
module.exports = server;
Test file:
// app.test.js
const app = require('../app');
describe('GET /', () => {
let response;
it('proves Jest works', () => {
expect(1).toBe(1);
});
it('proves maths still works', () => {
expect(1+1).toBe(2);
});
});
// remembering to CLOSE the server after tests completed.
afterAll(async () => {
await app.close();
});

Related

How to run Koa server before Tests in Mocha?

I read a lot of answers to similar questions already but can't figure out what is wrong in my code.
this is my server.js file
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
app.use(require('koa-bodyparser')())
const login = (ctx, next) => {
ctx.body = ctx.request.body
}
const router = new Router({ prefix: '/api' })
router.get('/test', (ctx, next) => {
ctx.body = { resp: 'GET REQUEST /test WORKING' }
})
router.post('/login', login)
app.use(router.routes())
module.exports = app
this is my index.js file
const server = require('./server')
server.listen(3000, () => {
console.log('App is running on http://localhost:3000')
})
and this is my mocha test file
const axios = require('axios').default
const expect = require('chai').expect
const app = require('./server')
describe('7-module-3-task', () => {
describe('test', function () {
let server
before(done => {
server = app.listen(3000, done)
})
after(async () => {
server.close()
})
it('should return response from server', async () => {
const response = await axios.get('http://localhost:3000/api/test')
expect(response.data, 'should return object with key "resp').to.have.property('resp')
})
})
})
It's working okay when I make a request in Postman. I tried multiple options already but I still get 404 response, as I understand test is performed before server started running...? How can I make it working ?
First, I would move the startup (app.listen) directly into the server.js (not critical, but maybe more simpler because the require in your test would then already start your server:
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
app.use(require('koa-bodyparser')())
const router = new Router({ prefix: '/api' })
router.get('/test', (ctx, next) => {
ctx.body = { resp: 'GET REQUEST /test WORKING' }
})
app.use(router.routes())
app.listen(3000); // can be a parameter but for simplicity hardcoded here
module.exports = app
In your test you then do:
let chai = require('chai');
let chaiHttp = require('chai-http');
let server = require('./server'); // this will already start up your server
describe('API Tests', () => {
describe('TEST endpoint', () => {
it('It should GET response from test endpoint', (done) => {
chai.request('http://localhost:3000')
.get('/api/test/') // be sure to have a trailing '/' !!
.end((err, res) => {
res.body.should.have.property('resp');
done();
});
})
});
});
One more hint: maybe in your original code you just have to make sure, that you have a trailing / when calling your route in the test.
Code snippets not testet but I hope you get the idea.
I shared the same code with 2 of my friends and they managed to run tests successfully.
I tested it on my other laptop after this and tests worked as well.
The problem was in the port. 3000 port was used as a default one in the debugger in Webstorm, not sure why but still.
Launching the server on port 3000 in a regular way, not in mocha tests, worked very well but in tests, it did not work, not sure why.
So for those who ever face something similar, check the default port of the debugger or any other built-in server.

Ensure express app is running before starting mocha tests

I built an API for a couchbase database, using express and node.js. My problem is that when I run my tests some of them fail, because the server is not fully running. I found a solution here https://mrvautin.com/ensure-express-app-started-before-tests on how to solve this issue. The article stated that in order to solve this issue, you have to add an event emitter in your server file like this
app.listen(app_port, app_host, function () {
console.log('App has started');
app.emit("appStarted");
});
and then add this, in your test file
before(function (done) {
app.on("appStarted", function(){
done();
});
});
I have tried this, here is my implementation
Server File
app.listen(config['server']['port'], function(){
app.emit("appStarted");
logger.info("Listening")
})
Test File
before(function(done){
app.on("appStarted", function(){
done();
})
});
I keep on getting the following error
1) "before all" hook in "{root}":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
The article is from 2016, so I was thinking that maybe the syntax has been deprecated. I was wondering if someone could please help point me in the right direction?
You can add the below condition, more info see "Accessing the main module".
if (require.main === module) {
// this module was run directly from the command line as in node xxx.js
} else {
// this module was not run directly from the command line and probably loaded by something else
}
E.g.
index.ts:
import express from 'express';
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.sendStatus(200);
});
if (require.main === module) {
app.listen(port, () => {
console.log('App has started');
});
}
export { app, port };
index.test.ts:
import { app, port } from './';
import http from 'http';
import request from 'supertest';
describe('63822664', () => {
let server: http.Server;
before((done) => {
server = app.listen(port, () => {
console.log('App has started');
done();
});
});
after((done) => {
server.close(done);
console.log('App has closed');
});
it('should pass', () => {
return request(server)
.get('/')
.expect(200);
});
});
integration test result:
(node:22869) ExperimentalWarning: The fs.promises API is experimental
63822664
App has started
✓ should pass
App has closed
1 passing (26ms)
!Hi World! My little solution here:
Check this: All depends of your testing markup...
For example, I'm using Mocha and Chai Assertion Library.
const express = require('express');
const request = require("request");
const http = require("http");
const expect = require("chai").expect;
require('dotenv').config();
describe('Server', function() {
const { PORT } = process.env;
const app = express();
before((done) => {
http.Server = app.listen(PORT, () => {
console.log(`Listening Node.js server on port: ${PORT}`);
done();
});
});
it('should return 404 response code status', () => {
const url = `http://localhost:${PORT}/api/v1/yourPath`;
return request(url, (err, response, body) => {
/* Note this result 'cause I don't have any get('/')
controller o function to return another code status
*/
expect(response.statusCode).to.equal(404);
});
})
});

Why Jest doesn't recognise Server instance with Express.js?

First, I'm a bit of a beginner. I created an Express project using express-generator which contains a file: bin/www. www is actually a javascript file containing the server creation like below code snippet:
#!/usr/bin/env node
// This file is generated by express generator
var app = require('../app');
var debug = require('debug')('happy-meal:server');
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function normalizePort(val) {}
function onError(error) {}
function onListening() {}
// Added by myself
exports.module = server;
The last line I added myself to get access to Server instance in jest test.
So, I want to run a simple integration test with the following code:
// integration test: users.test.js
const request = require("supertest");
describe("/api/v1/users", () => {
let server;
beforeEach(() => {
server = require("../../bin/www");
});
afterEach(() => {
server.close();
});
describe("GET /", () => {
it("should return all users", async (done) => {
const res = await request(server).get("/api/v1/users");
expect(res.status).toBe(200);
done();
});
});
});
This resulted in the following error output of jest:
TypeError: app.address is not a function
14 | describe("GET /", () => {
15 | it("should return all users", async (done) => {
> 16 | const res = await request(server).get("/api/v1/users");
| ^
17 |
18 | expect(res.status).toBe(200);
19 | done();
at Test.serverAddress (node_modules/supertest/lib/test.js:55:18)
at new Test (node_modules/supertest/lib/test.js:36:12)
at Object.get (node_modules/supertest/index.js:25:14)
at Object.<anonymous> (tests/integration/users.test.js:16:47)
● /api/v1/users › GET / › should return all users
TypeError: server.close is not a function
9 | });
10 | afterEach(() => {
> 11 | server.close();
| ^
12 | });
13 |
14 | describe("GET /", () => {
at Object.<anonymous> (tests/integration/users.test.js:11:16)
It looks like it doesn't recognise the "server"-variable as a Server object. Because of that, "server.close()" doesn't work, as a result the server is not shut down. Also the get-request doesn't work. Once again, the server object is not seen as a Server instance.
What am I doing wrong? I hope you can help me out here.
request(server) won't work, you have to use your app instance instead:
const app = require('../../app'); // Where your app instance is
...
const res = await request(app).get("/api/v1/users");
Also, try to import your server above all to see if it is recognized as Server object.
Edit
Either you want to create http server every test, either you want to do create http server once for all tests and then close it after tests end. Try this :
// integration test: users.test.js
const http = require('http');
const request = require("supertest")
const app = require('../../app'); // Where your app instance is
describe("/api/v1/users", () => {
beforeAll(done => {
server = http.createServer(app);
server.listen(done);
});
afterAll(done => {
server.close(done);
});
describe("GET /", () => {
it("should return all users", async (done) => {
const res = await request(app).get("/api/v1/users");
expect(res.status).toBe(200);
done();
});
});
});

NodeJS: Error found: listen EADDRINUSE :::3000?

I'm currently facing a bug that I can't resolve and I have been struggling for some hours.
I'm using the following versions:
Node: 8.11.3
Express: 4.16.3
Jest: 22.2.2
Mongoose: 5.2.3
I'm trying to do some integration tests with jest and I have 2 files with tests.
In each file I wrote the following:
// Create the server before each test.
beforeEach(() => {
server = require('../../index');
});
// Close the server after each test.
afterEach(async () => {
if (server) {
server.close();
}
});
In index.js I have the following (This is not all the code, but the relevant code for the bug):
// Listen to the server.
const port = config.PORT || process.env.PORT || 3000;
module.exports = app.listen(port, () => {
winston.info(`Listening to port ${port}...`);
});
When I run npm test
I get this exception all the time:
**listen EADDRINUSE :::3000**
10 | // Listen to the server
11 | const port = config.PORT || process.env.PORT || 3000;
> 12 | module.exports = app.listen(port, () => {
13 | winston.info(`Listening to port ${port}...`);
14 | });
15 |
I tried several ways to solve this by adding async await to beforeEach and for afterEach and tried also to put the sever.close in afterAll and in beforeAll but still got the same error.
Then, I tried to solve by doing this:
How Do I Shut Down My Express Server Gracefully When Its Process Is Killed?
But again, with no luck.
Finally, when I wrote all the tests in 1 file, it works without this error. Does anybody know how to solve this? I don't want to write all my integration tests in 1 file..
Thanks!
Try setting the --runInBand flag, this will run your tests sequentially.
https://jestjs.io/docs/en/cli#runinband
In package.json scripts:
"scripts": {
...
"test": "jest --watchAll --verbose --runInBand",
...
}
[UPDATE] On further investigation, while you can use --runInBand to run your tests sequentially, another option is to await the server.close() since it returns a promise. As such, in your afterEach:
...
await server.close();
...
[UPDATE] I believe a better way to solve this issue is to separate out the index.js file into an index.js and a server.js file. This enables you to pull your index.js file into your tests without .listen:
// index.js
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.status(200).send({ hello: "world!" });
});
module.exports = app;
Then in a separate server.js file:
const server = require("./index");
const PORT = process.env.PORT || 3001;
server.listen(PORT, () => {
console.log(`App running on: ${PORT}`);
});
module.exports = server;
When running your app, you run: node server.js.
This then enables you to test your routes by pulling your index.js file into your test as follows:
// test.js
const request = require("supertest");
const server = require("./index");
describe("GET /", () => {
test("should return status 200", async () => {
const res = await request(server).get("/");
expect(res.status).toBe(200);
});
});
I am following the same course and had the same issue. --runInBand solved it for me.
The issue here is requiring server file multiple times. You shouldn't require server file like that. Each time you do that, an instance starts, in your first test file an instance of server already started, while requiring server for your second file, it tries to start another instance, but then your server is already running on 3000 and hence the error.
I think your port 3000 is busy somewhere else Or maybe this app is running on somewhere else in the terminal, Check it and close all the instances of this app.
Or
Try to use below code:
// Listen to the server
11 | const port = config.PORT || process.env.PORT || 3001; // CHANGE POST 3000-> 3001
> 12 | module.exports = app.listen(port, () => {
13 | winston.info(`Listening to port ${port}...`);
14 | });

Mocha testing socketio middleware won't finish suite

I am testing an nodejs-app with a server and a client component on nodejs 8.9 with mocha.
For mocha to end properly, I have to make sure that all socketio and http-servers are closed after the tests have been run. This works fine with normal tests, but as soon as I register a middleware to the socketio-server, the mocha-process won't close and stay open forever.
Testcode (comment in the second test to see the problem, run via mocha test.spec.js):
// test.spec.js
'use strict'
const Express = require('express')
const Http = require('http')
const ioserver = require('socket.io')
const ioclient = require('socket.io-client')
const NODE_PORT = process.env.NODE_PORT || 3000
describe('Client', function () {
beforeEach(() => {
const express = new Express()
this._http = Http.Server(express)
this._ioserver = ioserver(this._http)
this._http.listen(NODE_PORT)
})
// this test works perfectly, even when I copy it and run it
// multiple times in this suite
it('should connect to a socketio-server', (done) => {
this._ioserver.on('connection', () => {
client.close()
done()
})
const client = ioclient.connect(`http://localhost:${NODE_PORT}`)
})
// this test also finished, but the suite hangs afterwards - as if
// a socket-client or socket-server was not closed properly.
it('should finish the test suite even with a middleware', (done) => {
this._ioserver.use((socket, next) => {
return next()
})
this._ioserver.on('connection', () => {
client.close()
done()
})
const client = ioclient.connect(`http://localhost:${NODE_PORT}`)
})
afterEach(() => {
this._ioserver.close()
this._http.close()
})
})
Any ideas why that happens?
So, the problem was, that the server closed the client connection on a successful connection event. The client did not get any information on that, but instead saw a failed connection and tried to reconnect. This opened a socket to the server again and because the server was already closed, the connection error kept coming.
This behavior stopped node from properly destroying all objects, which in turn explaines the hanging. The solution is to call done() only after the client has declared a connection open, not after the server has declared a connection open like so:
'use strict'
const Express = require('express')
const Http = require('http')
const ioserver = require('socket.io')
const ioclient = require('socket.io-client')
const NODE_PORT = process.env.NODE_PORT || 3000
describe('Client', function () {
beforeEach(() => {
const express = new Express()
this._http = Http.Server(express)
this._ioserver = ioserver(this._http)
this._http.listen(NODE_PORT)
this._client = null
})
it('should connect to a socketio-server', (done) => {
this._ioserver.on('connection', () => {
done()
})
this._client = ioclient.connect(`http://localhost:${NODE_PORT}`)
})
it('should finish the test suite even with a middleware', (done) => {
this._ioserver.use((socket, next) => {
return next()
})
this._client = ioclient.connect(`http://localhost:${NODE_PORT}`)
// if we wait for the server and kill the server socket,
// the client will try to reconnect and won't be killed
// by mocha.
this._client.on('connect', () => {
done()
})
})
afterEach(() => {
// this last call forces the client to stop connecting
// even if tests failed
this._client.close()
this._ioserver.close()
this._http.close()
})
})

Resources