Testing ExpressJS REST API with Mocha and Chai
ExpressJS is the most famous Node.js framework for creating Web Applications and REST API or so-called Micro Services. It provides a default MVC flavor along with “Micro-Service” flavor into a single package. It would be a bold statement, but I believe lots of frameworks have inspired from the intuitive and route-mapped callback driven Micro-Services in ExpressJS.
Lots of GUI based tools are used to test the REST APIs, Postman is one of the famous ones. But I feel and I strongly recommend that instead of using Postman, developers should develop a practice to test the API using Unit Testing Frameworks like Mocha and Chai.
In this article, we will quickly write a skeletal for Books API and perform CRUD Operations on Books Collection. We will use Chai and Mocha to test the REST API and also perform test automation along the way.
Before you Start
This article assumes that you know the basics of Node.js and Express.js. You should consider to download Node.js and Express.JS and install it on your machine and try some code before you try the stuff in this article.
If you are new to Express.JS then you should consider learning ExpressJS first. Take a look at this tutorial for learning the basics of Express.JS.
Getting Started
Lets create an Express.JS application using Express Generator Tool.
$ express rest-api
This will do the scaffolding for your Express project structure. If you know basics of express and have used express generator tool before, you know the drill.
$ cd rest-api && npm install
And then open the code in your favorite IDE.
The Books API
In this article, we will create Books API. We will perform CRUD operation for the for the Books Entity for a NoSQL DB.
To keep things simple let us consider only 4 fields for the Books Entity(in JSON) :
- ISBN
- Name
- Author
- Year (of publication)
A Sample JSON Value:
{
"isbn": "121212",
"title": "World Is Best",
"author": "Larry",
"year": "2016"
}
We will take up following CRUD Operations:
- Create Book
- Read Book (By ISBN)
- Read all Book
- Update Book (By ISBN)
- Delete Book (By ISBN)
- Delete All Books
I have a practice of creating [which every Ex-Java developer might have a practice of 😀] a Dao Class which will take care of the CRUD Functions. So before declaring the DAO, let’s write a global DB object in app.js, which we will pass in each function call to our Dao Functions.
Setting Up Mongo Driver for Node.js
We will be using MongoDB as noSQL in this Article. I am assuming that you have a version of MongoDB Community Edition installed on your machine and have some knowledge of noSQL and MongoDB Commands.
Installing MongoDB Driver for Node.JS
The simplest driver is “mongodb” npm module. To install it fire following on your Express Project Home Folder.
$ npm install mongodb
Setting Up Global DB Object
Let’s set up an application level object which will hold the DB Connection, which we will use in the DAO function calls. Add following snippets on your app.js file.
Make sure you have an instance of mongod
running on your machine when you execute this application and have a testdb
database created (or any db name of your choice).
Creating DAO
As discussed earlier, we will take up following CRUD Operations:
- Create Book
- Read Book (By ISBN)
- Read all Book
- Update Book (By ISBN)
- Delete Book (By ISBN)
- Delete All Books
Create a file in dao/BooksDao.js
in your express project and add following snippets in the file:
You can see that there are six functions for six CRUD operations we discussed. Now let's write code for one function to insert the book in the DB. It will have two arguments:
- Database instance
- Book Info
The above code uses promise to have an async function call. The code used Q library to have a “promise” mechanism. I suggest referring to promises and Q module if you are already not aware of the same.
If the insert is successful the promise will be resolved and status JSON will be returned to the routes, which can be analyzed and sent back in the response to the client. In case the insert was not successful, promise will be rejected and error will be handled in the caller function in wait state.
Let’s see the entire DAO with functionalities of all size CRUD operations:
Looking at the first function, the rest of the functions are quite intuitive.
Setting up the Route Middleware
Now we will have to wire the Books route middleware with the CRUD Operations. For those who know how RESTFul services work, its simple to map HTTP Methods with CRUD Operations:
- CREATE — POST
- READ — GET
- UPDATE — PUT
- DELETE — DELETE
Let’s see a code for Create operation (post method) and the rest of the functions will be intuitive from the same:
The BooksDao is called in this route handler file and we have called respective promise handling for success and error cases and mapping it with respective response to the client.
Now let’s see the complete code to digest what’s happening with the route handler:
Next step it to register the middleware to the app.use function, and we will do it in app.js which we see in next section.
Registering Middleware in App.js
Like all other routes, let's register our middleware module for /books
path:
Getting Started with Mocha and Chai
We will be installing the following modules of Mocha and chai:
- Mocha
- Chai
- Chai HTTP
To install the dependencies, you can fire the following command:
$ npm install mocha chai chai-http
Mocha and chai are very famous Unit Testing Frameworks for automated testing. We will be using chai-http
module to make HTTP Requests.
Creating a Test
Create a file test.js
in the test
folder of your express application folder:
We will be using some functions of Mocha and Chai framework for performing this tests:
- describe(): used to club multiple tests in one collection.
- it(): a single test unit, mentioning how it should behave and a callback to execute the test body.
- chai.request(): to make an HTTP Request to the REST API
- done(): metioning the test was successful.
- xx.should.xxx(): should is a great feature in chai library, helping us to assert the test condition. If the condition fails, the test fails. In simpler terms it’s sophisticated was to make test assertions.
Let's see a single test for deleting all the books:
To add the books:
To Fetch all the Books
Let’s add a test to fetch all the books:
To Fetch a particular Book
Let’s add a test to fetch all a particular book. We can add an ISBN statically in the route parameter:
To Update a Particular Book
Updating the book and testing whether the update was successful:
To Delete Book
Let’s write a test to delete a book, and then test to see whether delete was successful:
Putting it all together
Let’s see the complete collections of test just created:
Run the Test
Let’s add a test script in package.json
:
..."scripts": {
"start": "node ./bin/www",
"test":"mocha"
},....
To run the test, try the following:
$ npm test
The unit tests will be executed, calling the API and giving you the test result for your code.
Final Thoughts
I feel and I strongly recommend that instead of using GUI Tools, developers should develop a practice to test the API using Unit Testing Frameworks like Mocha and Chai. This will create a habit of unit testing and also enable us to create a template for automated tests in the future. This gives a comprehensive test environment than the ones in GUI Tools.
About the Author
Parth is a Trainer, Consultant, and Entrepreneur. He is also an author of the course “Learning Express.JS: Building Future Web Applications and API ”. His is passionate about training and have trained employees of multinational companies for topics like Java, Java EE, JS Frameworks and Python. He is a child prodigy in coding. His consulting firm takes up projects Regarding Open Source ERP Implementations, Blockchain, and IOT.