Tuesday, 1 March 2016

Testing callbacks in Node.js

When you're using any asynchronous language such as JavaScript or Node.js you will possibly be using callbacks. You will also want to make sure that you can unit test these callbacks successfully.

This blog describes a pattern for unit testing callbacks in Node.js using mochachai and sinon.

Let's say I have a function to get the details of a beer, as follows

var getBeerDetails = function(beerCode, onSuccess, onNotFound) {
    var beer = beerList[beerCode];
    beer !== undefined ? onSuccess(beer) : onNotFound();
};

The function takes three parameters, a beerCode and two callbacks. The callbacks are called when the beer is successfully found or when it's not found, as per the parameter names. The test for the "onSuccess" callback looks like this

it('should be called with beer object', function() {
    // Arrange
    var beerCode = '1001';
    var beerDetails = {
        abv: '4.1%',
        description: 'Light, hoppy, citrus flavours'
    };
    var onSuccessSpy = sinon.spy();
    var onNotFoundSpy = sinon.spy();

    // Act
    index.getBeerDetails(beerCode, onSuccessSpy, onNotFoundSpy);

    // Asssert
    expect(onSuccessSpy).to.be.calledWith(beerDetails);
    expect(onNotFoundSpy).not.to.be.called;
});

The key part of this test is using sinon to spy on the callbacks. This enables you to determine whether they have been called and with which parameters. This test asserts that the "onSuccess" callback to be called with the details of the beer found. To make this test even better we can also assert that the "onNotFound" callback is not called.

This is just some of the functionality sinon has, it's a very useful part of the unit testing toolkit.

The full source code for this blog can be found on GitHub at https://github.com/davet1985/beer-catalogue