Testing is necessary in Javascript development, but it's not always a fun experience. Lucky for us, there are a lot of testing frameworks that could make the process simpler than it was. One of these tools that we're going to talk about here is MochaJS.
What is it?
MochaJS, or simply called Mocha, is a tool that can help you test your Javascript applications. Mocha has a lot of APIs that do all the heavy-lifting, and leave you to do the minimum amount of work.
How to use it?
In this example, we're going to build a small npm module called math
. It consists of simple plus()
and minus()
functions. Here's the step-by-step process:
- Install
mocha
in your project.
npm install mocha --save-dev
- Create
src
folder and a JS file, main.js, inside of it. Here's the content of the file:
function plus(a, b) { return a + b; } function minus(a, b) { return a - b; } module.exports = { plus: plus, minus: minus };
- Create a
test
folder and a JS file called test.js inside of it. This folder will contain all the test cases that we'll be writing using Mocha. We'll be modifying this file a lot in a moment. For now, below is the content of the file. Each block enclosed by the keyworddescribe()
is called a suite. Each suite consists of one or more test cases that started with keywordit()
.
var assert = require('assert'); var math = require('../src/main'); describe('Math', function() { describe('#plus()', function() { it('should return 3', function() { assert.equal(math.plus(1, 2), 3); }); it('should return 5', function() { assert.equal(math.plus(3, 2), 5); }); }); describe('#minus()', function() { it('should return 1', function() { assert.equal(math.minus(2, 1), 1); }); it('should return 3', function() { assert.equal(math.minus(6, 3), 3); }); }); });
- Change the property of
test
in package.json like below:
{ ... "scripts": { "test": "mocha" }, ... }
- Enter this command to run the tests:
npm test
.
And, you're done!
Here's the final project structure:
.
├── src
│ ├── main.js
├── test
│ ├── test.js
├── package.json
That's the basic of Mocha. Now, here are a few features that you might need sometimes:
Use done()
when the test case is complete
If you're testing asynchronous functions, you might want to make sure that the callback is called multiple times. You can use done()
for this. For example:
describe('User', function () {
describe('#save()', function () {
it('should save without error', function (done) {
var user = new User('Luna');
user.save(function (err) {
if (err) done(err);
else done();
});
});
});
});
Mocha will throw an error if done()
is called more than once. And, as you can see above, you can pass Error
instance to it, as well.
Hooks
Hooks are functions that could be called before and after each test case or suite. Here's the example:
describe('Math', function () {
describe('#plus()', function () {
before(function() {
// called before all tests in #plus suite
console.log('#plus:before');
});
after(function() {
// called after all tests in #plus suite
console.log('#plus:after');
});
beforeEach(function() {
// called before each test in #plus suite
console.log('#plus:beforeEach');
});
afterEach(function() {
// called after each test in #plus suite
console.log('#plus:afterEach');
});
it('should return 3', function () {
assert.equal(math.plus(1, 2), 3);
});
it('should return 5', function () {
assert.equal(math.plus(3, 2), 5);
});
});
});
You can also put hooks outside of all the suites. It is called root-level hooks.
Pending Tests
Pending tests are test cases that will be written in the future. They're like a placeholder or a stub. Here's the example:
describe('#minus()', function () {
...
// pending test
it('should return null when a or b is null');
});
Inclusive and Exclusive Tests
Sometimes when you're testing a module, you only want to run a select few of test cases. Typically, you would commented the test cases that you don't want to run. But Mocha encourages you to use inclusive and exclusive tests instead.
For example, if you only want to run the first test case of '#plus()' suite, you could use exclusive test with the keyword only()
, like this:
describe('#plus()', function () {
it.only('should return 3', function () {
// only this test case will be run
assert.equal(math.plus(1, 2), 3);
});
it('should return 5', function () {
assert.equal(math.plus(3, 2), 5);
});
});
only()
can also be used in a suite.
On the other hand, you could use inclusive test to skip certain test cases or suites. For example:
describe('#plus()', function () {
it.skip('should return 3', function () {
// this test case will not be run
assert.equal(math.plus(1, 2), 3);
});
it('should return 5', function () {
assert.equal(math.plus(3, 2), 5);
});
});
Skipped test cases will be marked as pending by Mocha.
Others
There are a lot of other things you could do in Mocha. Here's some interesting ones:
- Dynamically writing test cases.
- By default, Mocha uses the built-in assert module for assertion. You can change this with other modules, such as chai.
- By default, Mocha uses Behavior-Driven Development (BDD) interface/DSL. You can change this with other interfaces, such as QUnit.