Idiot Note: MochaJS

Testing is necessary in Javascript development, but it's not always a fun experience. Lucky for us, there are a lot of testing frameworks that could make the process simpler than it was. One of these tools that we're going to talk about here is MochaJS.

What is it?

MochaJS, or simply called Mocha, is a tool that can help you test your Javascript applications. Mocha has a lot of APIs that do all the heavy-lifting, and leave you to do the minimum amount of work.

How to use it?

In this example, we're going to build a small npm module called math. It consists of simple plus() and minus() functions. Here's the step-by-step process:

  1. Install mocha in your project.
    npm install mocha --save-dev​
  2. Create src folder and a JS file, main.js, inside of it. Here's the content of the file:
    function plus(a, b) {
        return a + b;
    }
    function minus(a, b) {
        return a - b;
    }
    
    module.exports = {
        plus: plus,
        minus: minus
    };​
  3. Create a test folder and a JS file called test.js inside of it. This folder will contain all the test cases that we'll be writing using Mocha. We'll be modifying this file a lot in a moment. For now, below is the content of the file. Each block enclosed by the keyword describe() is called a suite. Each suite consists of one or more test cases that started with keyword it().
    var assert = require('assert');
    var math = require('../src/main');
    
    describe('Math', function() {
        describe('#plus()', function() {
            it('should return 3', function() {
                assert.equal(math.plus(1, 2), 3);
            });
            it('should return 5', function() {
                assert.equal(math.plus(3, 2), 5);
            });
        });
    
        describe('#minus()', function() {
            it('should return 1', function() {
                assert.equal(math.minus(2, 1), 1);
            });
            it('should return 3', function() {
                assert.equal(math.minus(6, 3), 3);
            });
        });
    });​
  4. Change the property of test in package.json like below:
    {
      ...
      "scripts": {
        "test": "mocha"
      },
      ...
    }
    ​
  5. Enter this command to run the tests: npm test.

And, you're done!

Here's the final project structure:

.
    ├── src
    │   ├── main.js
    ├── test
    │   ├── test.js
    ├── package.json

That's the basic of Mocha. Now, here are a few features that you might need sometimes:

Use done() when the test case is complete

If you're testing asynchronous functions, you might want to make sure that the callback is called multiple times. You can use done() for this. For example:

describe('User', function () {
    describe('#save()', function () {
        it('should save without error', function (done) {
            var user = new User('Luna');
            user.save(function (err) {
                if (err) done(err);
                else done();
            });
        });
    });
});

Mocha will throw an error if done() is called more than once. And, as you can see above, you can pass Error instance to it, as well.

Hooks 

Hooks are functions that could be called before and after each test case or suite. Here's the example:

describe('Math', function () {
    describe('#plus()', function () {
        before(function() {
            // called before all tests in #plus suite
            console.log('#plus:before');
        });

        after(function() {
            // called after all tests in #plus suite
            console.log('#plus:after');
        });

        beforeEach(function() {
            // called before each test in #plus suite
            console.log('#plus:beforeEach');
        });

        afterEach(function() {
            // called after each test in #plus suite
            console.log('#plus:afterEach');
        });

        it('should return 3', function () {
            assert.equal(math.plus(1, 2), 3);
        });
        it('should return 5', function () {
            assert.equal(math.plus(3, 2), 5);
        });
    });
});

You can also put hooks outside of all the suites. It is called root-level hooks.

Pending Tests

Pending tests are test cases that will be written in the future. They're like a placeholder or a stub. Here's the example:

describe('#minus()', function () {
    ...

    // pending test
    it('should return null when a or b is null');
});

Inclusive and Exclusive Tests

Sometimes when you're testing a module, you only want to run a select few of test cases. Typically, you would commented the test cases that you don't want to run. But Mocha encourages you to use inclusive and exclusive tests instead.

For example, if you only want to run the first test case of '#plus()' suite, you could use exclusive test with the keyword only(), like this:

describe('#plus()', function () {
    it.only('should return 3', function () {
        // only this test case will be run
        assert.equal(math.plus(1, 2), 3);
    });

    it('should return 5', function () {
        assert.equal(math.plus(3, 2), 5);
    });
});

only() can also be used in a suite.

On the other hand, you could use inclusive test to skip certain test cases or suites. For example:

describe('#plus()', function () {
    it.skip('should return 3', function () {
        // this test case will not be run
        assert.equal(math.plus(1, 2), 3);
    });

    it('should return 5', function () {
        assert.equal(math.plus(3, 2), 5);
    });
});

Skipped test cases will be marked as pending by Mocha.

Others

There are a lot of other things you could do in Mocha. Here's some interesting ones:

  • Dynamically writing test cases.
  • By default, Mocha uses the built-in assert module for assertion. You can change this with other modules, such as chai.
  • By default, Mocha uses Behavior-Driven Development (BDD) interface/DSL. You can change this with other interfaces, such as QUnit.