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
-
Install Mocha and Chai:
npm install --save-dev mocha chai- The --save-dev flag ensures these dependencies are installed only for development purposes.
-
Create the Test Folder:
mkdir test- The test folder will contain your test cases.
Step 2: Writing Your First Test
-
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.
-
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
-
Assert:
const { assert } = require('chai');
assert.equal(add(2, 3), 5, '2 + 3 should equal 5'); -
Expect:
const { expect } = require('chai');
expect(add(2, 3)).to.equal(5); -
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.
For further exploration: