Testing with Mocha and Chai in JavaScript Part 1

Introduction

Abhay Ahire
5 min readOct 7, 2023

Unit Testing is an essential aspect of software development. It ensures your code works as expected. Also prevents bugs from reaching production. Testing provides confidence when making changes to your code base.

Mocha and Chai are two powerful tools that make writing and running tests a breeze.
In this blog post, we’ll dive into the fundamentals of Mocha and Chai testing. We will cover everything from the initial setup to writing complex test suites in TypeScript.
Mocha is a testing framework that provides a structure for organising tests. On the other hand, Chai is an assertion library that helps you make assertions.

Section 1: Setting up the Environment

Before we can start writing tests with Mocha and Chai, let’s set up our development environment.
Here are the prerequisites:
Node.js: Ensure that you have Node.js installed on your system.
You can download it from the official website. https://nodejs.org/ennpm (Node Package Manager): npm comes bundled with Node.js.
Verify installation by using node -v and npm -v

Now, let’s install Mocha and Chai:
Open your terminal and create a project directory.
mkdir mocha-test
Run the following commands to install Mocha and Chai inside directory:
npm init -y
npm install --save-dev mocha chai
This command will add Mocha and Chai to your project’s package.json.

Congratulations! You’ve successfully set up the environment for Mocha and Chai testing. In the next section, we’ll write our first test.

Section 2: Writing Your First Test

Let’s start by creating a simple test suite and test case in JavaScript. In your project directory, create a new file, logger.js, and add the following code:

module.exports = {
greet: function () {
return "hello";
}
}

Now Add directory called test and inside that directory create a file loggerTest.js
Let’s modify package.json script to run test
Modify test command as below
“test”: “mocha”
Now let’s write our first unit test in loggerTest.js

const assert = require('chai').assert;
const greet = require('../logger').greet;

describe('logger', function () {
it('it should return hello', function () {
assert.equal(greet(), 'hello');
})
})

Let’s understand what we are doing here
Here’s a breakdown of the code
const assert = require(‘chai’).assert;
This line imports the assert function from the Chai library.
Assertions allow us to check whether the actual result matches the expected result.
const greet = require(‘../index’).greet;
This line imports the greet function from the logger.js file.
The greet function is what we want to test.
describe(‘Logger’, function(){…})
This is a Mocha test suite.
The describe function is used to group related test cases together.
In this case, we’re creating a test suite named ‘Logger’ to group our tests related to the logger functions.
it(‘it should return hello’, function () {…})
This is a Mocha test case.
The it function is used to define a single test case. Here we are describing what the test is supposed to check.
assert.equal(greet(),’hello’);
This line of code is the actual test. It uses the assert.equal function from Chai. It checks whether the result of calling the greet function is equal to the string ‘hello’.
If they are equal, the test case passes; otherwise, it fails.
Now, open your terminal and run Mocha to execute the test:
npm run test

aaa-host@ubuntu:~/mocha-tests$ npm run test
> mocha-tests@1.0.0 test
> mocha
Logger
✔ it should return hello

1 passing (3ms)

You should see an output indicating that the test passed. You’ve just written and executed your first Mocha and Chai test!
In the next section, we’ll explore Chai’s assertion methods in more detail and learn how to make various types of assertions.

Section 3: Using Chai Assertions

Chai provides several assertion styles to make your tests more expressive and readable. Here are three common assertion styles: expect, should, and assert for String
Create stringUtils.js file in your directory and add following snippets to it

module.exports = {
concatStrings: function (str1, str2) {
return str1 + str2;
},

capitalize: function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
},

countCharacters: function (str) {
return str.length;
},

containsSubstring: function (str, substring) {
return str.includes(substring);
},

replaceSubstring: function (str, oldSubstr, newSubstr) {
return str.split(oldSubstr).join(newSubstr);
},

splitIntoWords: function (str) {
return str.split(/\s+/);
},
};

Now to test this functions, create a stringUtilsTest.js inside test directory.

const assert = require('chai').assert;
const expect = require('chai').expect;

const stringUtils = require('../stringUtils');

describe('String Utilities', function () {
it('should concatenate two strings correctly', function () {
const result = stringUtils.concatStrings('Hello', ' World');
assert.strictEqual(result, 'Hello World', 'Concatenation failed');
});

it('should capitalize the first letter of a string', function () {
const result = stringUtils.capitalize('javascript');
assert.equal(result, 'Javascript', 'Capitalization failed');
});

it('should count the number of characters in a string', function () {
const result = stringUtils.countCharacters('Hello, World!');
expect(result).to.be.a('number', 'Character count is not a number');
expect(result).to.equal(13, 'Character count is incorrect');
});

it('should check if a string contains a substring', function () {
const str = 'Hello, World!';
const substring = 'World';
expect(stringUtils.containsSubstring(str, substring)).to.be.a('boolean', 'Result is not a boolean');
expect(stringUtils.containsSubstring(str, substring)).to.be.true;
});

it('should replace all occurrences of a substring in a string', function () {
const str = 'Hello, Hello, Hello';
const oldSubstr = 'Hello';
const newSubstr = 'Hi';
const result = stringUtils.replaceSubstring(str, oldSubstr, newSubstr);
expect(result).to.be.a('string', 'Replacement result is not a string');
expect(result).to.equal('Hi, Hi, Hi', 'Replacement failed');
});

it('should split a string into an array of words', function () {
const str = 'This is a test';
const result = stringUtils.splitIntoWords(str);
expect(result).to.be.an('array', 'Split result is not an array');
expect(result).to.deep.equal(['This', 'is', 'a', 'test'], 'Splitting failed');
});

});

In these assertions:

  • assert.strictEqual: Checks if two values are strictly equal (no type coercion).
  • assert.equal: Checks if two values are equal (with type coercion).
  • assert.isNumber: Verifies that the result is a number.
  • assert.isBoolean: Checks if the result is a boolean.
  • assert.isTrue: Asserts that the result is true.
  • assert.isString: Verifies that the result is a string.
  • assert.isArray: Checks if the result is an array.
  • assert.deepEqual: Compares two arrays or objects for deep equality.
  • expect(result).to.equal('value'): Checks if the result is equal to a specific value.
  • expect(result).to.be.a('type'): Verifies the type of the result.
  • expect(result).to.be.true: Ensures that the result is true.

These assertions cover various aspects of testing, such as type checking, equality, and deep comparisons, ensuring thorough testing of stringUtils functions. You can either use assert or expect depending on use case.
We will see test cases for more data types like Numbers, Arrays, Object in next part. Also Typescript Set up for Mocha and chai in next article.
Facing difficulties to understand the code, please find all source code over here. Github Unit Testing

Thanks for reading, we’ll continue this series and learn more about Testing with mocha and chai 🙂

--

--

Abhay Ahire

Full stack Dev with Angular, Java , Node and Devops Engg AWS