Jest, ExpressJS and the EADDRINUSE error

Abinav Seelan
campvanilla
Published in
3 min readFeb 10, 2018

--

Full Disclosure: Testing is something I have just begun delving into. This is more of a TIL post; something that I feel might be useful to someone looking for answers to what I had run into. 😄

For some context, I was trying to test my express routes using Jest when I ran into an obscure problem (at least, to me 😛) with EADDRINUSE.

To highlight what the issue is, let’s start off with a simple server file:

This server has two routes /ping and /status. The /ping route returns a simple text string “Pong!”, while /status returns the text string “Ok”.

Now let’s create tests for these routes using Jest and Supertest. For the sake of this article, let’s add the tests for each api in separate test files.

Let’s test /ping first:

On line 2, we include the server file and in our describe() block, we have a test that will make a GET request to the /ping api and check if the response’s text is “Pong!”.

Cool. Let’s run 🏃 this!

Everything seems to be working fine. ✅
Now let’s create another test file for /status.

The file status_test.js and checks if the text in the response from /status is “Ok”:

Let’s run 🏃 this again..

We get an EADDRINUSE issue.

The problem is this: once the execution of the first test ends, the server is still listening on the port 3000. So when we require('../server') again in the second test file, it errors out because is port is still in use by the previous test file’s process.

I initially assumed it to be an issue with Jest and the way it runs tests, but after a bit of googling, it turns out the issue is actually with the way we are running the server in the testing environment.

One simple fix for this issue is wrapping our 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, we do not really need to have the app listen on a network port.

So let’s fix this by adding a conditional check to server.js:

We’ve wrapped our app.listen() with a simple check on line 13 to check if process.env.NODE_ENV is test. We can add this environment variable by prepending our test script with NODE_ENV=test.

// package.json{
...
test: "NODE_ENV=test jest --forceExit", ...
}

Let’s see this in action! The tests run flawlessly now without any EADDRINUSE errors. 🎉

I’m just starting out with testing in general, so this may not be the best solution, but it’s the one that worked out for me. If you know of a better way to solve the EADDRINUSE while using Jest with Supertest, do let me know in the responses below! 🦄

~Fin~

If you found this helpful, do leave a 👏!

Stuck somewhere, need more help, or just want to say hi? Send me a Direct Question on Hashnode or hit me up on Twitter. You can also find me on Github. 🙃

--

--