Jest, ExpressJS and the EADDRINUSE error
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~