Getting Started with the Chai Assertion Library

23 Feb 2012 | By Jake Luer | Tags testing node tutorials

Jake Luer is a Node developer and consultant focused on helping to shape the next-generation of mobile and web applications. He is logicalparadox on GitHub and @jakeluer on Twitter.

Chai (GitHub: logicalparadox / chai, npm: chai, License: MIT) is a BDD / TDD assertion library for Node and the browser that can be delightfully paired with any JavaScript testing framework.

Chai aims to be an expressive and easily approachable way to write assertions for JavaScript project testing. Developers have already started expanding on Chai’s available language through plugins such as spies, mocks/stubs, and jQuery support. Starting out, however, I think you will find Chai’s language easy to pick up and powerful enough for even the most unruly of testing scenarios.

The motivation for Chai came about with the release of Mocha, TJ Holowaychuk’s incredible testing framework that can also be used with both Node and browsers. At the time, there was no apparent assertion library to pair with it that would allow for the same assertions to be used on both server and client with the inherent simplicity that Mocha provides.

The Basics

To get started in Node, add chai to your package.json under devDependacies. Or, if using in the browser, include the script in your page:

<script src="http://chaijs.com/chai.js" type="text/javascript"></script>

Chai currently supports all modern browsers: IE 9+, Chrome 7+, FireFox 4+, Safari 5+.

Assertion Styles

Chai comes packaged with three different assertion styles: expect, should, and assert. The expect and should interfaces are similar in that they are based on self descriptive language chains. The assert interface is similar to Node’s assert module but includes many more assertions.

For our examples we will assume the following:

var chai = require('chai')
  , foo = 'bar'
  , beverages = { tea: [ 'rooibos', 'matcha', 'oolong' ] };

First up is the BDD styles: expect and should:

var expect = chai.expect;
expect(foo).to.be.a('string').and.equal('bar');
expect(beverages).to.have.property('tea').with.length(3);

As you can see, the expect interface provides a function as a starting point for chaining your language assertions. Alternatively, the should interface extends Object.prototype with the single getter should as the starting point:

var should = chai.should();
foo.should.be.a('string').and.equal('bar');
beverages.should.have.property('tea').with.length(3);

Finally, the TDD style is exposed through the assert interface. This features the classic assert.test notation.

var assert = chai.assert;
assert.equal(foo, 'bar', 'Foo equal bar');
assert.length(beverages.tea, 3, 'We have three types of tea');

A few assertions that are also available are deep equality, exception testing, and instanceof. The full API documentation is available for all styles on Chaijs.com.

Extending Chai with Plugins

Though Chai provides all the basics of testing, we all know there can be much more to it. Chai can easily be extended through plugins that can add-on or modify Chai’s Assertion prototype. One example of this is logicalparadox/chai-spies, a basic function spying implementation.

Here is a simple example to assert that events have been emitted using chai-spies:

var chai = require('chai')
  , spies = require('chai-spies');

chai.use(spies);

var should = chai.should()
  , myspy = chai.spy(originalFn); // originalFn not required

eventemitter.on('some event', myspy);
// ... testing
myspy.should.have.been.called.twice;

The plugin approach makes it easy to use Chai for complex testing scenarios. Chai-spies is also a good resource for developers looking to build plugins that work for both Node and the browser.

These awesome developers have already started to build on Chai:

chai-jquery (License: MIT) by John Firebaugh provides deep jQuery integration with Chai’s `should` and `expect` styles.
$('#header').should.have.class('foo');
expect($('#title')).to.have.html('Chai Tea');
sinon-chai (License: WTFPL) by Domenic Denicola extends Chai with assertions for use with the Sinon.js mocking framework.
mySpy.should.have.been.calledWith('foo');
expect(mySpy).to.have.been.calledWith('foo');
jack (License: MIT) by Veselin Todorov is a mock/stub library that can be used as a stand-alone utility or with Chai.
mockedMethod.should.have.been.called.twice;
expect(mockedMethod).to.have.been.called.twice;

blog comments powered by Disqus