sou✌️ikinator
Testing Node.js APIs with Jest and Supertest

Testing Node.js APIs with Jest and Supertest

July 1, 2022
4 min read
Table of Contents

Here’s how to set up unit tests for API endpoints.

We’ll be using the following NPM packages:

  • Express for the server (any other framework can be used)
  • Jest
  • Supertest

VS Code extension using:

  • Jest
  • Jest Runner

Installing dependencies

npm install express
npm install -D jest supertest

Here is what the directory structure looks like:

and lets not forget package.json

{
  "name": "api-unit-testing",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest api.test.js",
    "start":"node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.1"
  },
  "devDependencies": {
    "jest": "^28.1.2",
    "supertest": "^6.2.3"
  }
}

Creating a simple express server

An express server that accepts POST requests with a body and title on the /post endpoint. If either one is missing, status 400 Bad Request is returned.

// app.js
const express = require('express')
const app = express()
 
app.use(express.json())
 
app.post('/post', (req, res) => {
  const { title, body } = req.body
 
  if (!title || !body)
    return res.sendStatus(400).json({ error: 'title and body is required' })
 
  return res.sendStatus(200)
})
 
module.exports = app
const app = require('./app')
const port = 3000
 
app.listen(port, () => {
  console.log(`http://localhost:${port} 🚀`)
})

The express app is exported for use with supertest. The same can be done with other HTTP server frameworks.

Creating test file

// api.test.js
const supertest = require('supertest')
const app = require('./app') // express app
 
describe('Creating post', () => {
  // test cases goes here
})

Supertest takes care of running the server and making requests for us, while we focus on testing.

The express app is passed to the supertest agent and it binds express to a random available port. Then we can make an HTTP request to the desired API endpoint and compare its response status with our expectation:

const response = await supertest.agent(app).post('/post').send({
  title: 'Awesome post',
  body: 'Awesome post body',
})

We’ll create test for 3 cases:

  • When both title and body are provided
test('creating new post when both title and body are provided', async () => {
  const response = await supertest.agent(app).post('/post').send({
    title: 'Awesome post',
    body: 'Awesome post body',
  })
 
  // comparing response status code with expected status code
  expect(response.statusCode).toBe(200)
})
  • When either of them is missing
test('creating new post when either of the data is not provided', async () => {
  const response = await supertest.agent(app).post('/post').send({
    title: 'Awesome post',
  })
 
  expect(response.statusCode).toBe(400)
})
  • When both of them is missing
test('creating new post when no data is not provided', async () => {
  const response = await supertest.agent(app).post('/post').send()
 
  expect(response.statusCode).toBe(400)
})

and the final code should look like:

const supertest = require('supertest')
const app = require('./app') // express app
 
describe('Creating post', () => {
  test('creating new post when both title and body are provided', async () => {
    const response = await supertest.agent(app).post('/post').send({
      title: 'Awesome post',
      body: 'Awesome post body',
    })
    expect(response.statusCode).toBe(200)
  })
 
  test('creating new post when either of the data is not provided', async () => {
    const response = await supertest.agent(app).post('/post').send({
      title: 'Awesome post',
    })
    expect(response.statusCode).toBe(400)
  })
 
  test('creating new post when no data is not provided', async () => {
    const response = await supertest.agent(app).post('/post').send()
    expect(response.statusCode).toBe(400)
  })
})

Running Test

Run test using following command:

npm run test

If using VS Code extensions like jest and jest runner then it’ll do the work for you.

And this is how we can easily test API endpoints. 💪