Get Started Quickly and Easily Testing With Mocha and Chai

Looking to test your JavaScript and/or TypeScript code? Then you could do worse than go for testing with Mocha and…

Testim
By Testim,

Looking to test your JavaScript and/or TypeScript code? Then you could do worse than go for testing with Mocha and Chai. These two libraries are among the most popular tools that developers use to write tests for JavaScript or TypeScript code. But if you’re not familiar with them yet, let me show you how easy it is to get started.

Introducing Mocha

Mocha is a unit testing library that runs both on Node.js and in the browser, allowing you to run your tests wherever it makes most sense to you. It also supports asynchronous code (callbacks, Promises and async/await).

A basic Mocha test will look something like this (taken from the documentation):

var assert = require('assert');
describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function() {
      assert.equal([1, 2, 3].indexOf(4), -1);
    });
  });
});

Basically, you describe certain features, modules and functions, and then assert that it should do something.

The assert object in the code above isn’t part of Mocha. This is where Chai comes into play.

Introducing Chai

In unit tests, we need a way of verifying that the result of our function calls are what we expect them to be. If you’re using Node.js, you can use the built-in assert module. But there are several other libraries out there that give you more convenient ways of asserting outcomes. Chai is one of these libraries.

Chai is an assertion library that contains different styles to assert. You can choose the “classic” assert-style, which looks like this:

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

// Your test code
assert.equal(foo, 'bar');

But Chai also includes a BDD-style syntax. Two actually: “expect” and “should.” Which one you use is a matter of personal preference.

The expect style looks like this:

var expect = require('chai').expect;

// Your test code
expect(foo).to.equal('bar');

And the equivalent with should:

var should = require('chai').should();

// Your test code
foo.should.equal('bar');

Like many other assertion libraries, Chai offers many convenient functions, that allow you to write your assertions in a human-readable form:

foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
beverages.should.have.property('tea').with.lengthOf(3);

Combined, Mocha and Chai give us all we need to write readable unit tests very easily.

A Sample Application

To get started with unit testing, we need a sample app. I’m going to write unit tests for JavaScript that will run in the browser, so we’ll be running our tests in the browser as well. Remember that Mocha and Chai will run fine for Node.js applications as well.

We’ll be testing some logic of the VanillaJS TodoMVC app. TodoMVC is a web application that has been written several times over using different JavaScript libraries. It can help you choose a framework for your web application. We’re going to use the Vanilla JavaScript implementation, meaning it doesn’t use any existing framework. Just pure JavaScript.

The easiest way to host it, is to download the code and host is locally. Just opening the index.html file in your browser won’t work, because most browsers block access to local storage when hosting from the file system. You’ll need a web server. A simple solution for this is to use the Web Server for Chrome extension. It gives you an easy UI that you can point to a folder:

Then, just navigate to the web server URL and you’ll see the app:

You can add items by entering text and hitting the Enter key.

The TodoMVC app already contains a test folder with some tests. Feel free to have a look, but for this article, we’re going to write our own tests from scratch. To avoid conflicts, you might want to remove the existing test file.

Installing Mocha and Chai

Installing Mocha and Chai is easy if you’re using npm:

npm i mocha chai -D

The “-D” flag installs it as a development dependency.

The Function to Test

We’ll start with a simple function to test. In the template.js file, you should see a clearCompletedButton function:

Template.prototype.clearCompletedButton = function (completedTodos) {
    if (completedTodos > 0) {
        return 'Clear completed';
    } else {
        return '';
    }
};

This function accepts a number indicating how many to do items have been completed. If it’s larger than 0, it returns “Clear completed.” If not, it returns an empty string. This is a piece of logic to show a button that will remove all completed tasks in our UI.

Our First Test

In the test folder, create a new file called template.spec.js and another called index.html. The index.html is where our tests will be hosted. You can run this file perfectly from the file system so there is no need for a web server this time. Just double-click on it to open it in a web browser.

Hosting the Tests

In the index.html file, paste this code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Mocha Tests</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
  </head>
  <body>
    <div id="mocha"></div>

    <script src="../node_modules/chai/chai.js"></script>
    <script src="../node_modules/mocha/mocha.js"></script>

    <script class="mocha-init">
      mocha.setup('bdd');
      mocha.checkLeaks();
    </script>
    <script src="../js/template.js"></script>
    <script src="template.spec.js"></script>
    <script class="mocha-exec">
      mocha.run();
    </script>
  </body>
</html>

A few things are important here:

  • We’re importing the mocha.css, mocha.js and chai.js files so that our tests can run and we see a nice report when they’re done.
  • We’re also importing our template.js so that we have access to the code in our test.
  • Then we’re referencing template.spec.js which will contain our test code.
  • And finally, we call mocha.run() to execute the tests.

If we open the index.html file in a browser now, we should see some text indicating the Mocha didn’t find any tests:

Writing the Tests

So, let’s write some tests. In template.spec.js, add the following code:

const expect = chai.expect;

describe('template', function() {
    describe('clearCompletedButton', function() {
        it('should return "Clear completed" when more than 0 items are completed', function() {
            var template = new app.Template();
            var result = template.clearCompletedButton(2);
            expect(result).to.equal('Clear completed');
        });

        it('should return an empty string when 0 items are completed', function() {
            var template = new app.Template();
            var result = template.clearCompletedButton(0);
            expect(result).to.equal('');
        });
    });
});

Here’s what’s happening:

  • As a convenience, I put Chai’s expect function in a separate variable. Remember that we referenced chai.js in our index.html file, so chai is now a global object.
  • Then we describe our template module, and inside that describe function, we’re describing the clearCompletedButton function. Inside this function, there are two tests, in the form of calls to the it function.
  • We’re using Chai’s expect function to verify the outcome of our calls to the clearCompletedButton function.

Notice how both the describe and the it functions accept two parameters: a string describing what it is we’re testing, and a function to be executed by Mocha.

If we refresh our browser, we’ll see this:

As you can see, we get an nice overview of our tests, how many passed or failed, and how long the run took.

You can continue to add tests as you build your application. In case any test fails, you’ll see a clear message of what went wrong. In this example, I deliberately made a test fail:

Mocha and Chai: A Great Combination

That’s all you have to do to get started. Testing with Mocha and Chai is a great combination and has proven itself in many scenario’s. They’re widely used, are well-maintained and have a good and vibrant community.

JavaScript code has become an important part of our web applications. That’s why it pays off to test it: both as a driver towards a better design, and as a way of reducing regression bugs when you make changes.

Combining Mocha with Chai gives you a powerful combination to achieve this.

This post was written by Peter Morlion. Peter is a passionate programmer that helps people and companies improve the quality of their code, especially in legacy codebases. He firmly believes that industry best practices are invaluable when working towards this goal, and his specialties include TDD, DI, and SOLID principles.