How to build and test your Rest API with Node.js, Express and Mocha

Standard

Heads up!

The blog has moved!
If you are interested in reading new posts, the new URL to bookmark is http://blog.valeriogheri.com/

 

If you need to build an API, you want it done quickly and simply and you love JavaScript, then this article is for you!
I’m going to show a simple, quick and effective way to build and unit test your API and your routes, using Node.js, Express and a few amazing test libraries: Mocha, SuperTest and should.js that integrate very well together in a natural fashion.
The API style is Rest, that is it leverages URLs and HTTP verbs, but I won’t go much into details in this tutorial.
If you ever used technologies such as WCF, you will be amazed at how much quicker it is to build your API with Node, there’s virtually no machinery to put in place, no service references to update, no WSDL… it’s pretty much just logic to implement!
Of course when you want to design your API around a Rest concept, it is very important to think about the access paths to your resources, they NEED to make sense and to be well structured, otherwise you just end up walking down the good old RPC path.
For a nice intro to this concept, see http://www.slideshare.net/domenicdenicola/creating-truly-res-tful-apis
By the way, in this tutorial I won’t cover advanced topics such as securing the API through HMAC or OAuth solutions.

From words to code:

A nice and free dev environment where to start coding is cloud9 (https://c9.io), as  it offers everything you need and maybe more: a text editor with syntax highlighting, a Node.js environment, a debugger (!), a shell, cloud storage and it connects to your GitHub repository… because you have a GitHub repository, don’t you? We don’t need more than that to write our first API, so let’s start!

Ok we want to write a HTTP API, so we obviously want our API to be accessible via some sort of webserver, but as you may already know, Node.js doesn’t come with its own webserver.
Instead it comes with some facilities built-in; on top of these facilities lies Express.js, the web server of choice for this tutorial. Express.js (http://expressjs.com/) describes itself as a web application framework for node, and I think you should use Express too, as it is a solid and well tested piece of software, easy to setup and test.

After reading some tutorials around, I came up with a structure of 4 short files  that setup and run the API:

  1. config.js exports an object that contains all configuration keys and values, pretty much like web.config in an Asp.Net web app. Following this line we can think about having a config-debug.js  and a config-release.js. We’ll see later why.

  2. routes.js exports a setup function that takes care of declaring the routes and the handlers that will manage each request.

  3. server.js where we configure Express and we export a start function that takes care of setting up the routes and starting the web server

  4. index.js is the entry point of our API. It uses pretty much everything we have defined so far to start the logger (my logger of choice is winston), to connect to a database, if present, and to finally start the Express server.

config.js

routes.js

As you can see, setup expects two parameters: app is the Express app and handlers is an object that maps to a set of functions that handles user requests. Each of these functions accepts as parameters the request and response objects: e.g.

function handleCreateAccountRequest(req, res) { … }

server.js

The first part is just some standard Express setup + Express logging.
Now we can see clearly what the parameters for routes.setup are: app is just the Express instance and handlers contains two objects that point to the different handlers that will be able to handle API requests.
Finally, after declaring and exporting the start function, this module exports the Express instance, which will be used in the tests.

index.js

As already said, index.js is the entry point, that means our API will be executed by running the command

$ node index.js

We can easily configure the API logger using winston and the configuration file, we connect in this case to MongoDB using mongoose, a fantastic tool, and then we start the server using the freshly exported function.
That’s it, you don’t need anything else to setup your API along with a solid logger and a database connection.

Ok I have an API but… how do I test it?

The test framework of choice for this tutorial is Mocha (http://visionmedia.github.io/mocha/) along with Supertest for HTTP assertions (https://github.com/visionmedia/supertest) and Should.js for BDD style tests (https://github.com/visionmedia/should.js). Mocha is a great choice because it makes async test natural and fluent.

The purpose here is to unit test our routes  (integration tests) and to build the tests so that we will be able to read our test and the results as if they were plain English sentences!
Let’s create a folder named “test” where we will place our test files and our mocha.opts configuration file where we can specify the output style for our tests.
Finally we can create our unit tests for the routes in a file called “test/routes.js”.

The structure of a test with Mocha is simple and verbose:

So if you try and read the test, it would come out something like:
Describe Routing, describe Account, it should return error trying to save duplicate username, it should correctly update an existing account, and so on.
To add more test, simply add more describe or it functions, and that’s it!

To execute the tests, start your api with

$ node index.js

and then in another shell run

$ mocha

as by default mocha will run everything in /test off of your main project.

If you want to run your test by typing

$ npm test

then all you have to do is to create a makefile and can even be as follows:

then add the following lines to your package.json file:

“scripts”: {
“test”: “make test”
}

and that’s the result (note that in the screenshot I have more tests as it’s taken from an actual project of mine)

Mocha test output with BDD style

Mocha test output with BDD style

That’s it, pretty easy, isn’t it?

About these ads

31 thoughts on “How to build and test your Rest API with Node.js, Express and Mocha

  1. Thanks – big help as I’ve just started a node.js/express RESTful API project.

    One question – what’s…

    var server = require(‘../Server.js’);

    …doing in your test file? (And why the uppercase ‘S’).

    • Hello,
      thanks for your kind comment!
      You’re right it’s a mistake of mine, I forgot to remove it from the test file.
      I think it was some experiment to start the API directly from the test file (and yes).

  2. sravan

    HI,

    Can u send me the mocha unit test sample for nodejs REST web service .I am using GET method and that service returns json output.
    Internally that service connects the oracle DB

    • Hello, thanks for your comment!
      Well about integration tests, I’d say that no matter how complex your API is, you have a finite set of HTTP Status codes, so you can write (at least) one test per return status code.
      If you are dealing with unit tests, try to keep each unit as simple as possible, so that it’s easier to test.
      Does this answer to your question?

  3. Hi, thanks for this excellent article.

    I’m having a bit of difficulty understanding the way you instantiate the different handlers. Could you give an example of how you’d code one of them ?

    Or better yet, do you have the full code of this article ?

    Thanks

    • Hello Luc, I’m sorry I didn’t make my self clear enough.
      Please check my repository located at for the full code https://github.com/vgheri/ShopWithMe
      An handler is just a plain javascript object, defined for example as:

      var AccountHandler = function() {
      this.createAccount = handleCreateAccountRequest;
      this.getAccount = handleGetAccountRequest;
      this.updateAccount = handleUpdateAccountRequest;
      this.deleteAccount = handleDeleteAccountRequest;
      };

      Then the module exports this function as:

      module.exports = AccountHandler;

      Then in your module which defines the start function of your server, you can do something like:

      var handlers = {
      account: new AccountHandler()
      // Here you can instantiate all your handlers
      };

      function start() {
      routes.setup(app, handlers);
      var port = process.env.PORT || 3000;
      app.listen(port);
      console.log("Express server listening on port %d in %s mode", port, app.settings.env);
      }

      Where routes is the module that defines your API routes. The handlers are injected into it as follows:

      function setup(app, handlers) {
      app.post('/api/profiles', handlers.account.createAccount);
      ...
      }

      exports.setup = setup;

      I hope this helps,

      Valerio

  4. Hi, thanks for the post. I have a pretty similar setup for testing.
    The issue I have now is that my API calls a third party API (google’s), and I would like to mock this third party call (so that I can run my test offline and use fake access tokens for the purpose of testing).
    I’ve looked into nock, but I feel like it only mocks the http calls for the test file, not for the API.
    How would you do that?
    Thanks!

    • Hello Martin, thanks for you comment!
      Mmm, maybe you can create a module that on API startup sets up nock to intercept the HTTP calls you want to mock, and then when from your test file you will request your API method, then that method will use the nock result.
      Because you don’t want this code to be there when you package your code for production, you may want to use GRUNT to automate it.

      Did I understand your question? What do you think about this solution?

      • Thanks a lot for your response! I’ve just seen it.
        Yes you perfectly understood my question. I was thinking of a similar solution in the meantime but I hoped there would be a better way. But hey, if you are thinking the same, it is probably the best way :-)
        I’m already using Grunt on the front-end (angularJS app) but yeah, using it on the backend too for that purpose is a good suggestion.
        Thanks again
        Martin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s