API Testing with Mocha and Chai

Cedric Damian
Practical Software Testing
4 min readMay 6, 2021

Hello there, welcome back to this article series of Javascript testing with Mocha and Chai. If you haven’t seen the first article of the series, have a read.

Now, after that coffee break, today we’ll be discussing how to test a simple REST API with Mocha and Chai in detail. So open up your editors and let’s get going. The code for this series can be found on Github.

In this article, we will add to our list of dependencies. Make sure to have these installed first:

npm i body-parser lowdb uuid supertest express

body-parser: This is a middleware that will parse our incoming request bodies

uuid: We will use this to generate unique ids.

lowdb: This is a small JSON database for node, electron, and the browser. Suitable for a small project like this one

supertest: A library for HTTP assertions

express: A Node.js framework

Next, we will need to have the API in place so go ahead and create an api.js file inside our test folder and in it, paste this code:

var express = require('express');var lowdb = require('lowdb');var filesync = require('lowdb/adapters/FileSync');var { v4: uuidv4 } = require('uuid');var bodyParser = require('body-parser');// Instantiate the appvar app = express();// Create a db.json file and load the lowdb adapter to allow read/write functionality on the db file(A new db.json file will be created for you when you run this file)var adapter = new filesync('db.json');var db = lowdb(adapter);// Set the default structure for the db filedb.defaults({posts: [],}).write();//Parse incoming request dataapp.use(bodyParser.json());// Routes for the API// Adding a taskapp.post('/add-task', function(req, res){var title = req.body.title;// Generate a new random IDvar id = uuidv4();// Reject any requests without the bodyif (!title || title === undefined){res.status(400).end()}else{// Add the new entry along an id to the db filedb.get('posts').push({ id, title }).write();return res.status(201).end();}});//Listing all tasksapp.get('/tasks', function(req, res){return res.json(db.getState());});//Listing a particular taskapp.get('/tasks/:id', function(req,res){var id = req.params.id;// Capture the id from the request and first check if it exists in the dblet a = db.get('posts').find({ id: id });if (a) {return res.json(a);}return res.status(404).end();});//Update a taskapp.put('/tasks/:id', function(req,res){var update = req.body.title;// Reject any requests without a bodyif (!update || update === undefined){res.status(400).end()}else{// Find the item in the db with that id and write the update to itdb.get('posts').find({id : req.params.id}).assign({title : update}).write();return res.status(200).end();}})// Delete taskapp.delete('/tasks/:id', function(req,res){db.get('posts').remove({ id : req.params.id}).write();return res.status(200).end();})// API server listing port 3000app.listen(3000, function() {console.log('API up and running');});module.exports = app;

Alright, with that out of the way, let us now write our API tests. In your test.js file, load these first:

const request = require('supertest');const app = require('./api')

Then add these lines under the last calculator test:

// API testsdescribe('POST /add-task', function() {it('Adds a task', function(done) {// Use supertest to run assertions for our APIrequest(app).post('/add-task').send({ title: "API testing rocks!" }).expect(201, done);});});describe('GET /tasks', function() {it('List all tasks', function(done) {request(app).get('/tasks').expect(200, done);});});describe('GET /tasks/:id', function() {it('Gets a particular task', function(done) {request(app)// Here, you should use the ids generated from the tasks you have in your db.get('/tasks/957095a3-fff0-47a5-9d2f-d64fddbd67e2').expect(200, done);});});describe('PUT /tasks/:id', function() {it('Updates a particular task', function(done) {request(app).put('/tasks/957095a3-fff0-47a5-9d2f-d64fddbd67e2').send({ title : "Updated task buoy" }).expect(200, done);});});describe('DELETE /tasks/:id', function() {it('Deletes a particular task', function(done) {request(app).delete('/tasks/8e88212c-2a05-4774-a371-9638cc897e52').expect(200, done);});});

Now when you run npm test in your terminal, you should see this in addition to the calculator results:

And there we have it, a simple REST API built with express and tested using Mocha, Chai, and Supertest. All detailed explanations have been commented in. Please feel free to seek clarification in the comments and if you liked the article, leave me a clap as you wait for the next article in the series. Cheers

--

--

Cedric Damian
Practical Software Testing

QA Automation Engineer || Frontend Developer || Lover of Life