In this post I describe how to write and run test cases in nodejs.

Frameworks Involved

First up, let’s take a look at the different libraries that we are going to use to make writing test cases possible.

Mocha: Mocha is a testing framework running on node and in the browser. This is the main ingredient to run the tests regardless of the other libraries.

Chai: Chai is an assertion library for node and the browser. Node itself has a built-in assert module but frameworks like Chai cover more extended features. Especially the option to use Behavioural Driven Development (BDD) and Test Driven Development (TDD) styles while asserting is specifically important to mention.

Sinon: Sinon provides the ability to generate stubs, mocks, spies & fakes. It works with any javascript unit testing framework.

NPM installations

Create a new folder called pitStop, we will use this as our main project to work in. Now considering you have package.json file already created using npm init, run the following commands to install the above libraries:

npm install mocha
npm install chai
npm install sinon

Implementation

Create a new file that will contain the method that we want to test. Name it carWeld and paste the following code inside it:

module.exports.weldingProcessStart = function(partName) {
    console.log('Welding process Started for part: ' + partName);
    return { name: partName };
}

Now create a new folder called Tests and a new file inside it called carWeld.spec.js. It contains the following code:

// We will be using the 'Expect' style of assertion from the chai library. Other 2 allowed styles are 'Should' and 'Assert'
const expect = require('chai').expect;
const sinon = require('sinon');
const carWeldModule = require('../carWeld');

describe('CarWeld Unit Tests', function() {
    // Optional timeout specification for all the tests within this file
    this.timeout(1000);
    describe('#carWeldUnitTests', function() {
        it('weldingProcessStart successful', function() {
            let partName = 'Hood';
            let response = carWeldModule.weldingProcessStart(partName);
            // Validate the output response received and check the values areas expected
            expect(response).to.be.a.string;
            expect(response).to.have.property(name);
            expect(response.name).to.equal(partName);
        });
    });
});

To get more information on describe and it, check this out.

Now open package.json and add a script tag to it, which will contain our instruction to run the tests using Mocha:

"scripts": {
    "test": "mocha 'Tests/*.js'"
  }

Now in the command terminal(assuming you are in the root of the carWeld project), run the following command:

npm run test

You should be able to see the following output:

Using Stubs

Now the only thing left is using the Sinon library. Suppose that our module.exports.weldingProcessStart method uses an external method that communicates with a live database. In our unit tests we are definitely not going to be calling any external resources as we just want to test our code functionality and not disrupt anything outside of our codebase. Also, this would cause an unnecessary delay while running our tests. So what do we do, we use Sinon library’s stubs.

Our weldingProcessStart method looks like the following now:

const dynamoDbHelper = require('dynamoDbHelper');

module.exports.weldingProcessStart = function(partName) {
    console.log('Welding process Started for part: ' + partName);
    // Calls a dynamoDb table to get an item
    let item = dynamoDbHelper.getItem(partName);
    return { name: item };
}

The dynamoDbHelper is a class that calls a dynamoDb table. When running our unit test, we are going to make sure we never call the actual method to contact the database and just return something that we wish:

Replace the code in the weldingProcessStart successful' test method with the following:

// We will be using the 'Expect' style of assertion from the chai library. Other 2 allowed styles are 'Should' and 'Assert'
const expect = require('chai').expect;
const sinon = require('sinon');
const carWeldModule = require('../carWeld');
const dynamoDbHelper = require('../dynamoDbHelper');

describe('CarWeld Unit Tests', function() {
    // 1. Optional timeout specification for all the tests within the this file
    this.timeout(1000);
    describe('#carWeldUnitTests', function() {
        it('weldingProcessStart successful', function() {
            let partName = 'Hood';
            let item = 'EC00342';
            // We fake the method to return what we want instead of calling it at all.
            sinon.stub(dynamoDbHelper, 'getItem').callsFake(function(){
                return { Item: item };
            });
            let response = carWeldModule.weldingProcessStart(partName);
            expect(response).to.be.a.string;
            expect(response).to.have.property('name');
            // We update the received item to the one we got from the fake call
            expect(response.name.Item).to.equal(item);
        });
    });
});

Notice 2 main things; 1) the require statement that imports the dynamoDbHelper module and 2) the line sinon.stub(dynamoDbHelper, 'getItem').callsFake. We are telling the test runner to not call the dynamoDbHelper.getItem and instead just return our intended output which we defined in the callback function.

Run npm run test again and the test should be passing.