Skip to content

Instantly share code, notes, and snippets.

@soheilhy
Last active March 18, 2022 05:23
Show Gist options
  • Save soheilhy/867f76feea7cab4f8a84 to your computer and use it in GitHub Desktop.
Save soheilhy/867f76feea7cab4f8a84 to your computer and use it in GitHub Desktop.
Mocha Tutorial

Testing Node.JS applications using Mocha

Mocha is a unittest framework for Node. In this document, we explain how you can test your javascript code and also your HTTP servers.

Installing Mocha

Use npm to install Mocha:

npm install mocha

npm installs Mocha in node_modules/mocha/bin/mocha. You can run Mocha test cases using the following command:

node_modules/mocha/bin/mocha test

By default, Mocha will run test.js in the current folder. Now, let's explain how you can write a test case.

Testing a Library

Let say, we have a calc.js file that implements addition and multiplication:

exports.add = function(i, j) {
	return i + j;
};

exports.mul = function(i, j) {
	return i * j;
};

We should write unit tests to make sure that there is no bugs in add and mul. We implement our test cases in test.js:

var assert = require('assert');

var calc = require('./calc.js');

// Tests are hierarchical. Here we define a test suite for our calculator.
describe('Calculator Tests', function() {
	// And then we describe our testcases.
	it('returns 1+1=2', function(done) {
		assert.equal(calc.add(1, 1), 2);
		// Invoke done when the test is complete.
		done();
	});

	it('returns 2*2=4', function(done) {
		assert.equal(calc.mul(2, 2), 4);
		// Invoke done when the test is complete.
		done();
	});
});

assert is a standard module that provides easy-to-use assertion functions. calc is our calculator module.

describe creates a suite of test cases, and it implements a test case. The first argument to it is an explanation of the test case, and the second parameter is the test case function to which Mocha passes a done object. done should be called whenever the test case is finished. Inside the test case function, you should implement your test. For example, we have checked that add(1, 1) returns 2, and mul(2, 2) return 4.

Now, if you run Mocha you should see the following output:

# node_modules/mocha/bin/mocha test


  Calculator Tests
    ✓ returns 1+1=2
    ✓ returns 2*2=4


  2 passing (6ms)

Usually we test much larger applications, and we need a better categorization for our test cases. For that reason, you can embed a describe in another describe. For instance, if we want to have separate test cases for addition and multiplication, we implement test.js as follows:

var assert = require('assert');

var calc = require('./calc.js');

describe('Calculator Tests', function() {
	describe('Addition Tests', function() {
		it('returns 1 + 1 = 2', function(done) {
			assert.equal(calc.add(1, 1), 2);
			done();
		});

		it('returns 1 + -1 = 0', function(done) {
			assert.equal(calc.add(1, -1), 0);
			done();
		});
	});

	describe('Multiplication Tests', function() {
		it('returns 2 * 2 = 4', function(done) {
			assert.equal(calc.mul(2, 2), 4);
			done();
		});

		it('returns 0 * 4 = 4', function(done) {
			assert.equal(calc.mul(2, 2), 4);
			done();
		});
	});
});

For this test.js, you should get the following output:

# node_modules/mocha/bin/mocha test


  Calculator Tests
    Addition Tests
      ✓ returns 1 + 1 = 2
      ✓ returns 1 + -1 = 0
    Multiplication Tests
      ✓ returns 2 * 2 = 4
      ✓ returns 0 * 4 = 4


  4 passing (6ms)

Testing a Server

There is nothing special about testing a server except that we need to run the server to be able to test that. Well, you shouldn't do that manually. After all, unit tests are all about automation.

Let's first write a simple HTTP server that echos 'Hello, Mocha!' when we send a get request to /:

var http = require('http');

// This is just an example HTTP server. Use your own application here.
var server = http.createServer(function(req, res) {
	res.writeHead(200);
	res.end('Hello, Mocha!');
});

// listen strats the server on the given port.
exports.listen = function(port) {
	console.log('Listening on: ' + port);
	server.listen(port);
};

// close destroys the server.
exports.close = function() {
	server.close();
};

You can use any framework that you'd like including express.js. The only important point is that you should somehow export the functions to start and stop the server. Here, we have exported listen(port) and close().

Now, let's implement test.js:

var http = require('http');
var assert = require('assert');

var server = require('./server.js');

describe('HTTP Server Test', function() {
	// The function passed to before() is called before running the test cases.
	before(function() {
		server.listen(8989);
	});

	// The function passed to after() is called after running the test cases.
	after(function() {
		server.close();
	});

	describe('/', function() {
		it('should be Hello, Mocha!', function(done) {
			http.get('http://127.0.0.1:8989', function(response) {
				// Assert the status code.
				assert.equal(response.statusCode, 200);

                                var body = '';
				response.on('data', function(d) {
					body += d;
				});
				response.on('end', function() {
					// Let's wait until we read the response, and then assert the body
					// is 'Hello, Mocha!'.
					assert.equal(body, 'Hello, Mocha!');
					done();
				});
			});
		});
	});
});

before and after are the functions you can use to run a code before starting and after finishing all testcases in your suite. In our example, we start run the server on port 8989 in before, and close it in after.

Now, we know that the server will be running. So, we just send a get request using http.get(), read the response, and make sure that the server has echoed 'Hello, Mocha!'

Have fun hacking with Mocha!

@dianavile
Copy link

Loved it, thanks for sharing. Was able to made first testing in Mocha:)

@nickprudnik
Copy link

Very nice! Thanks for this tutorial

@aderonkeakinyemi
Copy link

thank you for your help!

@zacscoding
Copy link

zacscoding commented Nov 23, 2018

thx for help :)
there is a typo
it('returns 0 * 4 = 4', function(done) {
assert.equal(calc.mul(2, 2), 4);
done();
});

@poornimahabib
Copy link

nice tutorial for beginners..Thank you

@Kaushal28
Copy link

Better tutorial that it's docs

@szb512
Copy link

szb512 commented Feb 26, 2019

Awesome.

@dandgerson
Copy link

Thanks a lot! Greate Article. For more obviousness you can make bold that string wich contain that for test running we need started server )))

@AravindReddyGuda
Copy link

can you please help me by testing a function which does not return anything but console.log('.......')

@sametpalitci
Copy link

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment