Testing a NodeJS Library with Mocha and Chai

I’ve asserted before that I am not a “professional developer” partly because I don’t test. There are three things in testing that are important – a willingness to put in the time to learn a test framework, the writing of the tests and the adoption of a testing methodology. Today, I’m going to do all three for my latest project – a configuration framework for NodeJS that I am writing.

Testing Methodologies

Let’s start with the adoption of a testing methodology. One could write the code and then write some unit tests that test that code to make you feel good about releasing the library. It’s not really a methodology.

Test Driven Development is the first of the methodologies I can discuss. In TDD, you write the tests first – based on what the code is meant to do. This requires a level of design, of course. You get to write code that your library should run. Then you continually write code until all the tests pass. You are pretty well guaranteed to have 100% test coverage because you are coding against the tests. Once the tests pass, the code is complete.

TDD does fall down in a couple of areas – most notably where state comes into play. TDD is not a good fit for UI testing, for example. In the case of a library, your API is a contract – it either passes or fails. If you have enough tests to describe the API fully, then you’ve got a good test suite. In the land of UI development, however, there are corner cases. What if a user does something unexpected? One could assert that the UI is also a contract between a user and the program, but there are lots of things that can happen; including device differences, environment differences and so on that make this not so straight forward an answer.

BDD (which is Behaviour Driven Development) is a similar methodology but describes behaviours, not unit tests. For example, in my configuration example – TDD would test each method; BDD would test the act of producing a valid configuration.

There are other tests that you should consider aside from unit tests. You should definitely do some tests that are end-to-end (normally abbreviated as E2E). In my example, I want to support a set of common patterns for producing configurations, so I definitely want to test those situations.

Choice: TDD – the writing of unit tests and some E2E tests for the common patterns.

Testing Toolsets

This brings us to testing tools. In the NodeJS world, there are choices. I often got stuck on the implementation details of tests and that caused me to spin, eventually leading me to dropping testing because I just couldn’t decide. In general, you need to decide on two pieces – an assertion library and a test runner. Based on my prior research, I decided on Mocha and Chai. Mocha is the test runner and Chai is the assertion library. There is good information on each website, so I’m not going to go into detail. Instead I’m going to focus on setting up testing on my project.

Writing Tests

I’m using TypeScript and Visual Studio to generate all my code for this library I am writing. In my previous post, I set up the project and loaded it into Visual Studio. Today, my first step is to create a folder called test. Since I have the Node Tools for Visual Studio installed, I can write-click on the tests folder and select Add > New Item… There is a Mocha UnitTest File as an option under Node.js in both a JavaScript and TypeScript variety. I like to be able to run my build process without compilation, so my library is written in TypeScript, but the Gulpfile and unit tests are written in JavaScript:


I have not included Mocha or Chai in my project. Since I am in Visual Studio, I can expand the npm view in my Solution Explorer, right-click on the dev node and select Install new npm packages…


Searching for Mocha and Chai is enough:


One of the neat things about this is the warning it gives you on Windows:


Yes, you want to run npm dedupe. Fortunately, npm3 will get rid of this annoyance, but it isn’t the default release yet. Back to the test file. I’ve got a class – Configuration – that I want to test. It has a number of methods that I also want to test individually. Each method will have a number of tests associated with it. I’ve created a configuration.js on the test directory. Mocha will run all of the JavaScript files in the test directory by default. Here is my initial code:

var expect = require('chai').expect,
    Source = require('../dist/Source');

describe('Source', function () {
    describe('.keys()', function () {
        // Tests for the Source.keys() method

    describe('.type', function () {
        // Tests for the Source.type property

    describe('.location', function () {
        // Tests for the Source.location property

    describe('.get()', function () {
        // Tests for the Source.get() method

The first line brings in the expect syntax from the Chai library. Chai supports three different syntax implementations – should, expect and assert. They are mostly similar but do have some minor implementation differences. I like the readability of expect so I’m going to use that. I also bring in my library under test. Finally, I describe the library of tests I am going to run – the outer describe says I am testing the Source class and the inner describes say I am testing a particular method. You can next as much as you want.

Writing the tests

Let’s take the type property. I try to think about the tests first. Here is my logic:

  • It is set by the constructor
  • It is read-only
  • It is a string

Here is my code:

    describe('.type', function () {
        it('should return a string', function (done) {
            var s = new Source('static');

        it('sould be the same as the constructor value', function (done) {
            var s = new Source('static');

        it('should be read-only', function (done) {
            var s = new Source('static');
            expect(function () { s.type = 'new-value'; }).toLocaleString.throw(Error);

I find these tests to be highly readable. Each test case is self-contained – you could run any of these tests by itself and not worry about the state of the test system.

Running Tests

Before running tests, you need to have mocha installed globally so you can run it:

npm install -g mocha

Now I need a stub of my eventual implementation:

class Source {
    constructor(type: string, filename?: string) {

    get type(): string {
        return null;

export = Source;

Running mocha gets me a whole bunch of errors, but look at the top of the output:


Now I can run mocha whenever I want. You will note that the stack trace from the assertion library is printed for each error. One of the things I like doing is working on “the next error” – you can do this easily with mocha -b:


Integrating into the Build Workflow

I want to integrate testing into my workflow. There are two things I want to do here:

  1. Run npm test to test the project
  2. Run Mocha as part of my Gulp standard pipeline

Adding npm test support is easy – just add a “test” entry to the “scripts” section of the package.json file:

  "scripts": {
    "test": "mocha"

Integrating into gulp is also easy. Use the gulp-mocha library:

gulp.task('build', ['compile'], function () {
    return gulp.src('./test/**/*.js', { read: false })
        .pipe(mocha({ reporter: 'spec' }));

Here, my compile task compiles my code into the distribution area, ready for testing and usage.

Wrap Up

I’ve said a few times in the past that I need to learn testing techniques. Mocha and Chai make it easy. Now all I have to do is ingrain testing into my development world – write tests first and then code to the test. At least I have the tools and workflow to do this task properly.