The best (and worst) of Mocha, JavaScript unit testing

Have you ever made a change in your JavaScript code, and some time later you find that something stop working? Is there a way to avoid this? Of course, unit testing. And in JavaScript? Yes, Mocha

 

Unit tests

All we’ve ever developed, have encountered such situations. Maybe you were trying to fix a bug, or just writing a little feature, and then, suddenly, other parts of the software stop working. The way to avoid this is with unit testing. Unit tests check that a little piece of code (usually a function) works properly.

There is a development methodology based in unit tests: TDD (Test-driven development). It consists in creating, at the beginning of the development, unit tests that will check our software works ok. But in practice, many times unit tests are developed after we have finished the development. As a result we are creating incomplete and tailor made unit tests. Even so, they will be useful avoiding future changes breaking current functionality. But, if we start the implementation with unit tests, we make sure our software will accomplish all little features. Besides, we’ll prevent from breaking something that is already working.

 

JavaScript unit testing

Is there any tool to implement JavaScript unit tests? Yes, there are lots of tools that help to implement JavaScript unit tests. In this link you can compare some of them. Its features, pros and cons, in order to choose one of them, I decided to use Mocha. This tool is simple and so flexible that allows you to add multiple libraries that make it as powerful as we want. Even so, basic version of Mocha is more than enough for us to build the unit tests that will test our basic functions.

 

mocha javascript unit tests success failure

 

 

Mocha

Mocha is based in Node.js, so we will need to have it installed (How to install Node.js).
How to install Mocha:

npm install mocha -g

How to execute Mocha in our project?

mocha

It’s easy, isn’t it?
Now, we are going to create our first unit test. Inside our project we create a folder called test. In this folder we will put all the .js files (JavaScript) with the unit tests. By default, Mocha will search in this path and it will execute the files inside.


var assert = require("assert");

describe("Numbers",function(){
  it('should add two numbers',function(){
    assert.equal(5, 3 + 2);
  })
});

 

If we execute mocha in the root path of the project, console output will look like this:

Mocha, unit tests javascript. console output

 

This is a very simple example. It checks the result of adding two numbers is correct. We aren’t still calling any method of our JavaScript development. But it helps us to see how is the syntax.

 

Mocha syntax

assert: Comparing values, making sure the value returned for a function is the expected one.
describe: For grouping unit tests, nesting so many times as you need
it: The implementation of one unit test.

Other useful functionalities:
before: It is inside of a describe section. It will be executed before any of the unit tests (it) of the section. We can initialize variables that will be used in the unit tests execution
after: It will be executed after all of unit tests of the section. It should be used to keep the system in the same state at it was before section started.
beforeEach and afterEach are other two methods that will be executed before and after each unit tests of the section.

Mocha. Unit tests javascript.

A library used with Mocha is Chai:

npm install chai -g

Chai has several functionalities for checking values. It overwrites the assert method adding some functionalities, like checking if a value is greater than or less than other, or if an object is not null.

 

Async unit tests

Creating JavaScript unit tests one problem usually appears: working with asynchronous testing. In this case, Mocha doesn’t know on its own if the test is an asynchronous one, neither when it has finished testing or when the before / after method has finished. To solve this problem, we can call the callback method received as a function param. It is usually called done.
Let’s see a more complete example, with before and after methods. Besides, we will use async methods to initialize the database and to reset after testing. This force us to use the callback done to tell Mocha when every step has finished.
We have a MongoDB with a collection called channels where we store Channel documents which have a name. We also have a JavaScript file that manages the access to this collection. In this section of unit tests we want to test the get methods to retrieve Channel documents from the collection. We require the JavaScript file we want to test (channels.js).
We use the before function to make sure the collection has at least 3 Channel documents. Saving in MongoDB is an asynchronous process, and forEach method is asynchronous too. We have to use callback done to warn Mocha when the initialization process has finished. We will make the opposite process in the after function. It will remove the 3 documents to reset the MongoDB to the initial state. The 2 it functions will test the get methods that retrieve documents from the collection, checking that there are at least 3 documents (assert.isAtLeast). The other one checks that getting one document by id returns a not null object (assert.isNotNull)

 


var assert = require('chai').assert;
var channelsDB = require('../db/channels');
var channelNamesArray = ['test channel 1', 'test channel 2', 'test channel 3'];


describe('Channels', function () {
  describe('#get()', function () {
    var channelIds = [];

    // Create 3 channels in DB
    before(function (done) {
      var numChannelsCreated = 0;
      channelNamesArray.forEach(function (channelName) {
        var channel = new channelsDB.Channel({name: channelName})
        channel.save(function (error, channel) {
          if (error) throw error;
          channelIds.push(channel._id);
          numChannelsCreated++;
          if (numChannelsCreated == channelNamesArray.length) {
            done();
          }
        })
      })
    })

    // remove the 3 channels created before
    after(function (done) {
      var numChannelsRemoved = 0;
      channelNamesArray.forEach(function (channelName) {
        channelsDB.getChannelByName(channelName, function (error, channel) {
          if (error) throw error;
          channel.remove(function () {
            numChannelsRemoved++;
            if (numChannelsRemoved == channelNamesArray.length) {
              done();
            }
          })
        })
      })
    })


    it('Should get all channels without error', function (done) {
      channelsDB.getChannels(function (error, channels) {
        assert.isAtLeast(channels.length, 3);
        done();
      })
    })


    it('Should get one channel by id without error', function (done) {
      channelsDB.getChannel(channelIds[0], function (error, channel) {
        assert.isNotNull(channel);
        done();
      })
    })
  })
})

 

 

This is the output executing now

 

Mocha. Unit tests javascript.

 

Next time you start a JavaScript project, will you use unit tests and Mocha?

 

Mocha, JavaScript uni tests

 

 

Related artilces

 

Unit Tests in JavaScript with Sinon

Control the Code Style of Your Team: ESLint in JavaScript

Share on LinkedInTweet about this on TwitterShare on FacebookShare on Google+Buffer this page

Leave a Comment

By completing the form you agree to the Privacy Policy