January 8, 2016

Testing Javascript with Mocha and Chai

Continuation from the previous post.

The basic pattern for tests as I’ve introduced in the previous post makes use of the assert module from Node.js and a boolean condition to test for, eg.

assert(1==='one');
// throws AssertionError

Since Mocha will catch any error that has been thrown as an indication that the test has failed, other assertion libraries can be used.

Chai is an assertion library that includes more convenience functions than the basic assert module such as isUndefined, include, instanceOf etc. Chai also allows one to write these assertions in different styles which try to make specifying tests more natural.

// Assert style
assert.typeOf(name, 'string');

// Expect style
expect(name).to.be.a('string');

// Should style
name.should.be.a('string');

You can read more about the styles here. Personally, I prefer the Assert style since it is more similar to how I usually write code.

Installing Chai is just a simple

npm install chai

using the package manager npm.

Then, to use the Assert style of writing assertions, use Chai’s assert instead of the one from Node.js and you are ready to start writing assertions.

var assert = require('chai').assert;
var error;

assert.isUndefined(error);

Bonus

Chai has a number of plugins which extend Chai’s functionality for various use cases. The ones I tried and like so far are the Chai as Promised and chai-subset plugins which extend Chai with assertions for Promises and subsets of objects respectively. Here are two examples for using these plugins.

// Chai as Promised
var fs = require('fs');
var chai = require('chai');
var assert = chai.assert;
chai.use(require('chai-as-promised'));

var p_readFile = new Promise(function(resolve, reject){
    fs.readFile('filename.txt', function(err, data){
        if(err) {reject(err);}
        else {resolve(data);}
    });
});

describe('Read file async', function(){
    it('should successfully read the file', function(){
        return assert.isFulfilled(p_readFile);
    });
});
// chai-subset
var fs = require('fs');
var chai = require('chai');
var assert = chai.assert;
chai.use(require('chai-subset'));

var contents = fs.readFileSync('data.json');
var jsonData = JSON.parse(contents);

describe('Get JSON data', function(){
    it('should at least have the necessary values', function(){
        var user = {
            id: 1,
            name: {first: 'Firstname', last: 'Lastname'}
        };
        assert.containSubset(jsonData, user);
    });
});
- ksami