Testing NodeJS Express App

Poorshad Shaddel
Webtips
Published in
4 min readOct 4, 2020

--

Testing NodeJS Express App
NodeJS Express Integration Test

What is an integration test?

“ Integration tests determine if independently developed units of software work correctly when they are connected to each other. The term has become blurred even by the diffuse standards of the software industry, so I’ve been wary of using it in my writing. In particular, many people assume integration tests are necessarily broad in scope, while they can be more effectively done with a narrower scope. “ Martin Fowler.

Testing an Express app

So as to see how we can test an Express app we need to create a simple Express application. I used MongoDB and its native driver(We usually use Mongoose as an ODM) but in order to keep it as simple as possible I didn’t use Mongoose also, I implemented users directly in app.js which is not a good practice but it helps us to focus on how tests are working. You can take a look at this repository to see a better boilerplate for your NodeJS app.

Installing packages

express: we need express to implement our routes.
jest: Jest is our testing framework and it gives us a test environment.
supertest: we use Supertest for making requests.
mongodb: It is MongoDB native driver(For simplicity we are not using an ODM).
mongodb-memory-server
: This is an in-memory mongodb database and we are going to use it to run our tests.

package.json

Create a Jest config file

Jest needs a jest.config.js file to find our test files.

jest config file

* My project express app files are inside src folder so in line 2 I used <rootDir>/src
* In line 3 we need to enter a regex to separate test files from source files. This Regex returns true when the file has test.js or spec.js extensions or it is under __test__ folder(Jest recommends putting tests in this folder).

Create an Express app

This is a simple express app and the body-parser is used to handle the body of post requests.

Create a database connection

We need two kinds of the database :

  • Permanent database: It can be a docker container or mongodb cloud or a service on your local machine which persists data of the application.
  • Test database: Usually people use a temporary database which is fast so we can run our tests faster. We can use an in-memory version of mongodb using packages(we use this way in this example because it is easier :) ) or we can use a docker.

How do we know that we are testing?
By using environment variables. When we run tests using Jest this variable is process.env.NODE_ENV equal to test.

So when we are in development or production mode we can use a permanent database and in test mode, we need to use another database.

So let’s create a simple connection file :

creating a database connection

Now we are going to scrutiny this file line by line.

getDB function(4–16): This function gets an instance of the database connection(The better practice of getting an instance of connection is using a Singular pattern you can see one way of implementing this pattern in this article).
getTestDataBaseURL function(18–25): In order to run tests we need an in-memory database and we are going to use mongodb-memory-server npm package. This package creates a mongodb database on a random free port(you can use a static port by passing options to your instance). When we are creating an instance by calling its constructor we can use getUri function to get the database URL. this promise returns a URL like this : mongodb://localhost:27021
module.exports(27–42): We want to use an in-memory database when we are testing so we can use a condition an check the value of process.env.NODE_ENV .

Why we used the condition line 31? if (!URL){}
Each time we create an instance of MongodbMemoryServer there is a new raw database and by checking the URL value I don’t want to create a new instance of MongodbMemoryServer , the first time I create an instance I change the URL variable so next time I use that URL instead of creating a new mongodb in-memory database.

Find users and insert user

Getting users and insert one user

We implemented these routes inside app.js .

Test!

Finally, we are ready to implement our tests.

An imperative point is that we need to import our express instance here.
By using supertest package we can make requests.
this is the way we can make a request using supertest:

const res = await request(app).get('/users');

Since the database is empty we expect users to be [] .

In the second test, we are inserting a user and we are getting users so we expect the users to be an array with one element.

In the last test, we are inserting a user and we expect the response to have properties like insertedCount .

This was a simple example of testing an express application and this is the repository.

--

--

Poorshad Shaddel
Webtips

Full Stack Developer with more than 6 years of expericence. I spend partial part of the day working with Node.js and React.