NodeJS Back-End Web Testing

Setting up testing with Mocha, Chai, & Chai-HTTP

Introduction

Mocha, Chai, & Chai-HTTP are tools for running back-end web server tests. The world of testing is very confusing with tons of libraries. This is the simplest version I have found for getting back-end testing up and running for nodejs servers.

What This Tutorial Covers

1. We'll cover installing Mocha, Chai, & Chai-HTTP on your servers.

2. We'll create a basic test.

Most of the code will either be in a server.js file or a test/mytest.js file. We'll be assembling test/mytest.js in pieces, but the final look of the code will be at the bottom.

What You Need For Just The Tutorial

You need Nodejs installed. These are tools for testing nodejs servers, so obviously you need node.

You need NPM installed. NPM is the node package manager. You need it to install the dependencies.

You need a server script. We'll be using an ExpressJS server as an example, so I make the assumption that you have ExpressJS installed in your project. Otherwise, you need to supply your own node server script.


What The Project Directory Should Look Like

When we're done creating everything, your project directory should look similar to below:

Docs file hierarchy
  • Expand all
  • Collapse all
  • node_modules - npm installed dependencies end up here
    • ...a bunch of stuff here
  • test - testing files go in here
    • mytest.js - our basic test
  • package.json - this should exist after running npm install
  • server.js - a javascript file that runs and returns a server object

Install Mocha, Chai, Chai-HTTP

@@PROJECT-DIRECTORY@@

The directory of your project, where your node javascript server files live.

Installing these dependencies can all be done using npm. We're saving them as --save-dev, which means you can exclude them from your production build by running npm install --production.

copy
cd @@PROJECT-DIRECTORY@@
npm install --save-dev mocha
npm install --save-dev chai
npm install --save-dev chai-http

Configure package.json

We need to tell npm to use Mocha as our testing framework. That is configured in your package.json file, which should be in your project directory after running the npm install command.

Make sure the "script" section of @@PROJECT-DIRECTORY@@/package.json looks like below:

copy
"scripts": {
	"test": "mocha"
},

Create Test Folder & Test File

All of our testing files can be named whatever you want, but they must be in a folder called "test".

copy
mkdir @@PROJECT-DIRECTORY@@/test
touch @@PROJECT-DIRECTORY@@/test/mytest.js

Set Up Mocha Outline

Mocha is the testing framework. When we run our tests, npm will run Mocha. Mocha will open files in our testing directory and run any tests it find inside. Mocha tests, look like the code below.

Mocha is structured with the expectation that you'll be testing object-oriented design, although you don't have to use it that way. So where you see 'Class' would typically be named after the class you're testing or a related group of tests. Where you see '#method' would typically be named after a class method you're testing or a related group of functionality. Each test though, lives inside the it() function. It's first parameter is a string that describes what you want the test result to be. That style originated from BDD (Behavior Driven Developement), which is a philosphy on testing. The code below goes into the file test/mytest.js

copy
describe('Class',function() {

    before(function() {
        // runs before all tests in this block
    });

    after(function() {
        // runs after all tests in this block
    });

    beforeEach(function() {
        // runs before each test in this block
    });

    afterEach(function() {
        // runs after each test in this block
    });
	
    describe('#method',function() {
	    // this is one test
        it('should do something',function(done) {
				// check stuff here
                done();
            });
        });
    });
});

Create/Import Your Server

In order to test your server, you need to import it into your test. Make sure your server is configured so that it can be imported using require(). If you don't have a server set up, you can use the code below as an example. I'm assuming your server is in a file called server.js, so that is where the code below will go if you use it.

copy
// use module.exports so we can require() this code in another file.
module.exports = function() {
				
var express = require('express');

// this is our only server route
function route(request,response) {
	var qs = require('querystring');
	
	request.on('data',function(data) {
        body += data;
    });
    
    request.on('end',function() {
		var POST = qs.parse(body);
		
		if(POST.input !== '') {
			var message = { input : POST.input };
			response.setHeader('content-type','application/json');
			response.end(JSON.stringify(result));
			return;
		}
		
		response.end('');
	});
};	

// set route function to respond to root path
app.get('/',route);

// start the server
app.listen(2020,function(){});

// return the server object
return app;

};

Now in our test file test/mytest.js, you import it like the code below. That will run the function in our server.js file and return our expressjs "app". So now "server" refers to our expressjs "app" object.

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

If you want to pass parameters into your server so you can change the server configuration when you require it, your code will look like below:

copy
// inside mocha test
var server = require('../server.js')(parameter);

// inside your server file
module.exports = function(parameter) {
	// etc.
}

Import Chai & Chai-HTTP

Chai is an assertion library, which is just a fancy way of saying it has a bunch of functions for testing whether the result you get is equal to the result you want. Chai-HTTP is a plug in for Chai that extends its ability to make assertions on an http server, like the expressjs "app" we are using. Finally, we'll be using the "should" syntax, so we'll be grabbing that object from Chai. Importing and setting all this up looks like the code below and goes into test/mytest.js

copy
var chai = require('chai');
var chaihttp = require('chai-http');
var should = chai.should();
chai.use(chaihttp);

Creating Our First Test

So now we should have everything set up like below, and you'll see there is a simple test set up now. If you want more information on how the "should" syntax works, check out this link http://chaijs.com/api/bdd/. The code below goes into test/mytest.js

copy
var chai = require('chai');
var chaihttp = require('chai-http');
var should = chai.should();
chai.use(chaihttp);

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

describe('Class',function() {

    before(function() {
        // runs before all tests in this block
    });

    after(function() {
        // runs after all tests in this block
    });

    beforeEach(function() {
        // runs before each test in this block
    });

    afterEach(function() {
        // runs after each test in this block
    });

    describe('#method',function() {
        it('should return json with our input message',function(done) {
            chai.request(server)
            .post('/')
            .send("input=our message")
            .end(function(err,res) {
                should.not.exist(err);
                res.should.have.status(200);
                res.body.should.be.a('object');
                res.body.should.have.property('input');
                res.body.input.should.equal('our message');
                done();
            });
        });
    });
});

We passed our server object to chai.request().

Then we made a post request to the root path with .post("/").

Then we added a string to the body of our post request with .send("input=our message")

Finally, we ended our request with .end().

The callback inside of .end() has the response from our server and there we can test what we were expecting.


Running Our Test

Now all we have to do to run our tests is to go into our project directory and run a simple npm command:

copy
cd @@PROJECT-DIRECTORY@@
npm test

If all goes well, you should see the test run and pass. You can change "our message" in the test or some other property to see it fail.

Not too bad right?