Skip to main content

Unit Testing with Mocha and Chai: A Comprehensive Guide

What Are Mocha and Chai?

  • Mocha: A feature-rich JavaScript test framework running on Node.js, making asynchronous testing simple and fun. It provides a structured way to organize your test cases.

  • Chai: A BDD/TDD assertion library for Node.js and the browser. It provides expressive and readable assertions, making tests easier to write and understand.

Prerequisites

  • Node.js (v14 or higher recommended)
  • A code editor (e.g., Visual Studio Code)
  • Basic knowledge of JavaScript and Node.js

Step 1: Setting it Up in our Repos

  1. Install Mocha and Chai:

    npm install --save-dev mocha chai

    • The --save-dev flag ensures these dependencies are installed only for development purposes.
  2. Create the Test Folder:

    mkdir test

    • The test folder will contain your test cases.

Step 2: Writing Your First Test

  1. Example Function: A simple function that adds two numbers.

    // math.js
    function add(a, b) {
    return a + b;
    }

    module.exports = { add };

    Inside the test folder, create a file named math.test.js:

    // math.test.js
    const { expect } = require('chai');
    const { add } = require('../math');

    describe('Math Functions', () => {
    it('should return the sum of two numbers', () => {
    const result = add(2, 3);
    expect(result).to.equal(5);
    });

    it('should return a number', () => {
    const result = add(2, 3);
    expect(result).to.be.a('number');
    });
    });
    • describe: Groups related test cases.
    • it: Defines a single test case.
    • expect: An assertion style provided by Chai.
  2. Run the Test: Add a test script to package.json:

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

    Run the test using:

    npm test

Step 3: Adding More Tests

Expand your tests to cover more cases. For example:

// math.test.js
const { expect } = require('chai');
const { add } = require('../math');

describe('Math Functions', () => {
it('should handle negative numbers', () => {
const result = add(-2, -3);
expect(result).to.equal(-5);
});

it('should handle adding zero', () => {
const result = add(5, 0);
expect(result).to.equal(5);
});
});

Step 4: Using Different Assertion Styles in Chai

  1. Assert:

    const { assert } = require('chai');
    assert.equal(add(2, 3), 5, '2 + 3 should equal 5');
  2. Expect:

    const { expect } = require('chai');
    expect(add(2, 3)).to.equal(5);
  3. Should:

    require('chai').should();
    add(2, 3).should.equal(5);

Step 5: Testing Asynchronous Code

Modify math.js to include an async function:

function asyncMultiply(a, b) {
return new Promise((resolve) => {
setTimeout(() => resolve(a * b), 1000);
});
}

module.exports = { add, subtract, asyncMultiply };

Update math.test.js:

const { asyncMultiply } = require('../math');

describe('asyncMultiply()', () => {
it('should return 6 when 2 and 3 are multiplied', async () => {
const result = await asyncMultiply(2, 3);
expect(result).to.equal(6);
});

it('should return 0 when 0 and 5 are multiplied', async () => {
const result = await asyncMultiply(0, 5);
expect(result).to.equal(0);
});
});

Run the tests again to validate.

Step 6: Structuring Your Tests

Organize your test files by module or feature like the example below:

project/
├── src/
│ ├── math.js
│ └── string.js
├── test/
│ ├── math.test.js
│ └── string.test.js
├── package.json
└── README.md

Step 7: Generating Coverage Reports

Use nyc (Istanbul) to generate coverage reports:

npm install nyc --save-dev

Add to package.json:

 "scripts": {
"test": "nyc mocha"
}

Run the tests:

npm test

  • View the coverage report in the terminal or as an HTML file.
tip

For further exploration: