Blog.

Using Mocha Chai Sinon to test Node.js

MF

Marco Franssen /

7 min read1323 words

Cover Image for Using Mocha Chai Sinon to test Node.js

In this article I'm going to show you how to write tests for your NodeJS application using Mocha, Chai and Sinon.

Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.

One of the cool things is you can choose your own assertion style when writing Mocha tests. In this article I will use Chai to do my assertions.

Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any JavaScript testing framework.

Chai supports 3 assertion styles. Should, expect and assert. This makes Mocha and Chai the ultimate combination to make your testing suite completely fit your own project needs and desires.

As a mocking framework I choose Sinon since it integrates neatly with Mocha and Chai and dozens of other test frameworks.

Standalone test spies, stubs and mocks for JavaScript. No dependencies, works with any unit testing framework.

In order to start with writing your tests we first need to install Mocha, Chai and Sinon. Since I use Mocha for multiple projects I choose to install Mocha globally.

npm install -g mocha
npm install --save-dev mocha chai sinon

To be sure the consumers of my node package also have mocha installed I also add it to the dev dependencies. Since I installed Mocha globally it won't be installed in my package folder again. Now we can actually start writing our tests.

Lets assume we have the following folder structure for our package.

MyMochaChaiSinonExample
|_ lib
|_ spec
   |_ helpers

In the lib folder we have our JavaScript modules. In the spec folder we will save our tests / specifications. The helpers folder we will use to store our own helper scripts for our tests.

First off all I want to configure Chai so we won't have to define the configuration in each test. To do so I create a file chai.js in the specs/helpers folder.

var chai = require("chai");

chai.config.includeStack = true;

global.expect = chai.expect;
global.AssertionError = chai.AssertionError;
global.Assertion = chai.Assertion;
global.assert = chai.assert;

In the above configuration we configure Chai to include the stacktrace on failing assertions. We also made the Chai expect and assert methods available globally. We will require this helper file when executing our tests using the mocha test runner.

Next we can write our tests / specifications to cover our code from lib. Lets assume we have a calculator in our lib we want to unit test.

var EventEmitter = require("events").EventEmitter,
  util = require("util"),
  processResult = function (calculator, result, callback) {
    calculator.emit("result", result);
    if (typeof callback !== "undefined") {
      setTimeout(
        function () {
          callback(result);
        },
        1000,
        this
      );
    } else {
      return result;
    }
  };

function Calculator() {
  EventEmitter.call(this);
}

util.inherits(Calculator, EventEmitter);

Calculator.prototype.add = function (a, b, callback) {
  var result = a + b;
  return processResult(this, result, callback);
};

Calculator.prototype.substract = function (a, b, callback) {
  var result = a - b;
  return processResult(this, result, callback);
};

Calculator.prototype.multiply = function (a, b, callback) {
  var result = a * b;
  return processResult(this, result, callback);
};

Calculator.prototype.divide = function (a, b, callback) {
  var result = a / b;
  return processResult(this, result, callback);
};

module.exports = Calculator;

The calculator supports 3 ways to show us the result of the calculation. Synchronously via a return value, and asynchronously via a callback or an event. First I will show you how to write a synchronous test for testing the return value.

var Calculator = require("../lib/calculator");

describe("When adding one and two using the calculator", function () {
  var calculator;

  before(function () {
    calculator = new Calculator();
  });

  it("should result in three using the return style approach", function () {
    var result = calculator.add(1, 2);
    expect(result).equal(3);
  });
});

This test is a pretty straight forward test. We describe the test case, then we create a new calculator before we specify our assertion. In this example we used the expect style of chai. In the next example I will show you how to test asynchronous code. Therefore I will use the callback approach in my test since it is delaying the result by 1 second.

var Calculator = require("../lib/calculator");

describe("When substracting six and eight using the calculator", function () {
  var calculator;

  before(function () {
    calculator = new Calculator();
  });

  it("should result in minus two the callback approach", function (done) {
    calculator.substract(6, 8, function (result) {
      assert.equal(result, -2);
      done();
    });
  });
});

In the above test I also used a different assertion style, assert, to make my assertion. Also notice the done callback parameter. This parameter is used to tell Mocha the test has completed.

As a last example I want to show you how you can test if a certain function is called using a Sinon stub and spy. To do so I'm going to test the calculator using the event approach. In the test I want to make sure the result event is emitted before the callback is invoked.

var Calculator = require("../lib/calculator"),
  sinon = require("sinon");

describe("When multiplying nine and three using the calculator", function () {
  var calculator, eventEmitterStub, callbackSpy, clock;

  before(function () {
    calculator = new Calculator();
    clock = sinon.useFakeTimers();
    eventEmitterStub = sinon.stub(calculator, "emit");
    callbackSpy = sinon.spy();
  });

  it("should emit the event before the callback", function (done) {
    calculator.multiply(9, 3, callbackSpy);
    clock.tick(1000);
    assert.equal(callbackSpy.called, true);
    assert.equal(eventEmitterStub.calledWithExactly("result", 27), true);
    assert.equal(eventEmitterStub.calledBefore(callbackSpy), true);
    done();
  });

  after(function () {
    clock.restore();
  });
});

Since the callback is invoked after one second I want to make sure my assertions are executed when all the code of my calculation has executed. Therefore we use the Sinon fakeTimers. By doing so we are able to test if the callback is called and we are able to test if the emit method is called before the callback. If we would have skipped the clock then the assert on the spy would fail because the code hasn't executed yet. Using the stub we can monitor calls to the emit method which our object inherits from the EventEmitter.

Now it is time to learn how we can execute those tests using Mocha. Using the following command we execute all our tests from our specs folder.

mocha specs --require specs/helpers/chai.js

or use following command to have more visual feedback, since above command only shows you dots.

mocha specs --require specs/helpers/chai.js --reporter spec

As a bonus I would like to give you my gruntfile configuration to execute the tests automatically using the grunt watch job. Also note I will only include the files ending with *.spec.js. This makes sure the helper scripts won't be used as source files to our tests. As a convention I choose to have all my tests/specifications files end on *.spec.js.

mochaTest: {
    specs: {
        options: {
            ui: 'bdd',
            reporter: 'spec',
            require: './specs/helpers/chai'
        },
        src: ['specs/**/*.spec.js']
    }
}

/////////////////////////////////////////////

grunt.LoadNpmTasks('grunt-mocha-test');

Add the mochaTest task to your watch job tasks so your tests will be executed automatically. Don't forget to install the grunt-mocha-test package to your package.json

npm install --save-dev grunt-mocha-test

Last, but not least I would like to give you some helpful links to the webpages of all three frameworks.

Hopefully this article helps you to have a quick start on testing your own Node.JS packages using Mocha, Chai and Sinon. I also would like to challenge you to try using Mocha for testing your browser JavaScript. Feel free to share your experiences and questions using a comment on this article.

You have disabled cookies. To leave me a comment please allow cookies at functionality level.

More Stories

Cover Image for Packer.io machine building and provisioning part 2

Packer.io machine building and provisioning part 2

MF

Marco Franssen /

In the previous part of this series we had a look on building a bare Debian VM with the bare minimum packages installed to run a web server. In this part we will have a look on how we can improve our packer script with user variables and how to use the file and shell provisioner. User variables Variables can be easily added to the packer script by adding following JSON. Best practice is to put your variables as the first property in your JSON, before your builders. This way you have all the c…

Cover Image for Packer.io machine building and provisioning part 1

Packer.io machine building and provisioning part 1

MF

Marco Franssen /

Large development teams are often coping with the "It works on my machine" syndrome. One solution to solve these kind of issues is by give each single developer the same VM, which is most preferably the same as your production server. So imagine your company is building a web application. The web application is hosted on a Debian server using Apache, MySQL and PHP. So considering these preconditions I will give you a simple example to get your machines scripted and fully provisioned. In this fir…

Cover Image for Automate your development tasks using Grunt

Automate your development tasks using Grunt

MF

Marco Franssen /

Grunt is an extremely useful Node.js package to automate lots of development and continuous integration tasks. The Grunt eco-system has lots of packages available on npm. This enables us to quickly setup our development/continuous integration environment. Grunt tasks mostly have two required properties. An files array, which is used to configure on what files the tasks is executed, and an options property which configures some task specific settings. The files array supports the globbing and mi…

Cover Image for npm tips and tricks

npm tips and tricks

MF

Marco Franssen /

In my previous post I showed you how easily you can create a simple webserver using Node.js. In this post I want to show you how to make more advanced usage of node package manager. npm init Using node package manager you can get an even quicker start of your project by using the npm init command. So let's get started by opening a command prompt (on windows open the Node.js command prompt). Then create a new folder and navigate into this newly created folder. In the folder execute following co…