Testing your Express.js Backend Server
Tags: testing, javascript, beginners, codenewbie
Published: 2021-02-03 21:28:06

Recently I have been learning about Node, and building a backend API server with Express. Express.js allows for use of the MVC pattern similarly to Ruby on Rails for building a RESTful CRUD API (making a good learning transition for me). While learning how to implement all of the CRUD pieces with Express, I wanted to test the functionality to verify things were working properly. This blog post will explain how to test the CRUD functionality of routes in your Express backend API, with the use of Jest framework and SuperTest library.

## Express Server
I am assuming that you have an Express server running for this article, but below is a simple sample app to get the tests within this article running (below I will share some additional articles on building an Express server). In the code below you will find two example `GET` endpoints, along with some sample code to give you an idea of what your route might ACTUALLY look like when built out further.
```
// server.js
import express from 'express';
const app = express();

app.get('/users', function(req, res) {
  res.json({ users: 'allUsers' });
  
  // Real code from my application below
  //  model.User.findAll().then (users => {
  //        res.status(200).json({ users });
  //     }).catch(error=>{
  //        console.log(error)
  //        req.status(500).send(error)
  //  })
});

app.get('/users/3', function(req, res) {
  res.json({ user: 'user3' });
  
  // Real code from my application below
  // const { id } = req.params;
  //    model.User.findOne({
  //        where: { id: Number(id) }
  //    }).then(user=>{
  //        res.status(200).json({ user });
  //    }).catch(error=>{
  //        console.log(error)
  //        req.status(500).send(error)
  //    })
});

export const server = app;
```
Looking through the above routes, we see two `GET` requests: one for ALL users, and one for a SELECT user. Our tests will verify that each `GET` request will return a status code `200`, have `json` content type, and include the property we want to see returned (such as `users`, or `user3`).

## Setting Up Jest & SuperTest
First and foremost, we have to set up the testing environment. Below are the steps to getting Jest and SuperTest up and running.
##### 1. Installing Our Dependencies
```
npm install jest --save-dev
```
```
npm install supertest --save-dev
```
```
npm install cross-env --save-dev
```

##### 2. Setting up the testing environment
To set up the testing environment, we need to adjust the `package.json` folder in your Express application. The following settings allow you to run `npm test` in the CLI, which will perform a reset of the test database, migrate and seed your database each time for accurate testing purposes. 
* Note `NODE_ENV=test` being used to specify the test environment.
```
// package.json
 "scripts": {
    ...
    "test": "cross-env NODE_ENV=test jest --testTimeout=10000",
    "pretest": "cross-env NODE_ENV=test npm run migrate:reset",
    "migrate:reset": "npx sequelize-cli db:migrate:undo:all && npm run migrate",
    "migrate": "npx sequelize-cli db:migrate && npx sequelize-cli db:seed:all",
  }
```

We need Jest to ignore our `./node_modules` folder, so we also need to add this snippet of code to `package.json`:
```
...
 "jest": {
    "testEnvironment": "node",
    "coveragePathIgnorePatterns": [
      "/node_modules/"
    ]
  },
...
```

OK, now to try running a test with `npm test` in the command line. Now that we have our testing environment up and running, we should be able to start writing our tests!

## Writing Tests
We will be working in a new `test.js` file, and our goal is to test the functionality of the two `GET` requests above: 
`/users` and `/users/3`.
##### Import
We first need to import some dependancies so we can test our Express server. These go at the top of our `test.js` file. 
```
//test.js

const server = require('../index.js');
const supertest = require('supertest');
const requestWithSupertest = supertest(server);
```
You will notice that we are using `requestWithSupertest`, which links each test to the server.
##### Get all Users
The first thing we need is our initial `describe` block which will house BOTH of our tests. In this test, we will be checking how the `/user` GET route functions.
```
describe('User Endpoints', () => {

  it('GET /user should show all users', async () => {
    const res = await requestWithSupertest.get('/users');
      expect(res.status).toEqual(200);
      expect(res.type).toEqual(expect.stringContaining('json'));
      expect(res.body).toHaveProperty('users')
  });
  
});
```
In the code above, you notice we have added `await` to `requestWithSupertest.get('/users')`, because we are testing a promise that needs to be fulfilled before moving forward. We then expect to see a `200` status, `json` content type, and for the response body to have the `users` property. These three expectations fulfill what we wanted to test for in this route's functionality.

##### Get a User by ID
Ok, so we have our first test written. Now for the second test we will make a similar test, this time targeting the `/users/3` route. This test is supposed to show how you can test for a GET route of a targeted user id. This test will also be placed within the same `describe` block we defined above.
```
  it('GET /user/:id should show a user', async () => {
        const res = await requestWithSupertest.get('/users/3')
        expect(res.statusCode).toEqual(200)
        expect(res.body).toHaveProperty('user3')
    });
```
##### Run the Tests
Awesome! We have written two tests to verify functionality of our two sample `GET` routes. Now to run the tests in the command line:
```
npm test
```
You should see two passing tests in our test suite!

## Conclusion
You now have the resources to add some testing to your Express API! Hopefully the above examples help you to gain some initial understanding on how to set up and test the functionality of your Express server! I wanted to expand my knowledge of testing Express backend API requests, and this is how I set up tests within my own application!

Some additional resources I have used to help me learn Express.js and how to test the server include
[Node.js Rest APIs example with Express, Sequelize & MySQL by bezkoder](https://bezkoder.com/node-js-express-sequelize-mysql/)
[Building an Express API with Sequelize CLI and Unit Testing! by Bruno Galvao](https://levelup.gitconnected.com/building-an-express-api-with-sequelize-cli-and-unit-testing-882c6875ed59)
[How to test your Express.js backend with Jest and Supertest by Coderslang](https://dev.to/coderslang/how-to-test-your-express-js-backend-with-jest-and-supertest-3g83)
[Hopscotch.io - a tool to send server requests and see the responses](https://hoppscotch.io/)

---
**Has this article helped you get started with testing your Express server? Respond with comments or recommendations!**