Testing backend requests with hapi and lab

I found it surpisingly difficult to find sample code testing an a hapi.js service that makes a web request to another service. So I'll share what I came up with, you can find the full working code here https://gist.github.com/robjoh/41e76afd82656db54be9

The server

This server simply makes a call to http://date.jsontest.com and returns the date from the response.

var Hapi = require('hapi')  
var Boom = require('boom');  
var request = require('request');  
var server = module.exports = new Hapi.Server();

server.connection({  
  host: 'localhost',
  port: 8080
});

server.route({  
  path: '/',
  method: 'GET',
  handler: function(req, reply) {
    request.get('http://date.jsontest.com', function(err, response, content) {
      if (err) {
        return reply(Boom.wrap(err));
      }

      switch(response.statusCode) {
        case 200:
          return reply(JSON.parse(content).date);
        case 404: 
          return reply(Boom.notFound());
        default:
          return reply(Boom.create(500));  
      }
    });
  }
});

if (!module.parent) {  
  server.start(function() {
    console.log('started');
  });
}

Setting up the test

In addition to Lab and Code, I'm using the Sinon mock/spy framework to intercept the request.get function. I make sure to restore request.get to it's previous implementation after each test.

describe('server', function() {  
    var options = {
        url: '/',
        method: 'GET'
    };
    var requestStub;

    beforeEach(function(done) {
        requestStub = Sinon.stub(request, 'get');
        done();
    });

    afterEach(function(done) {
        requestStub.restore();
        done();
    });

});

Testing the 404 case

To verify the 404 response case, I simply tell the stub to return a response with a 404 status.

    it('handles a 404 status', function(done) {
        requestStub.yields(null, {statusCode: 404});

        server.inject(options, function(response) {
            expect(response.statusCode).to.equal(404);
            done();
        });
    });

Testing the happy path

In these tests, I want to verify that I am calling the service as expected.

The first test verifies the request. In it I grab the value supplied by the request.get call from the service.

The second test is verifies the response this server emits which should be a 200 with the date as content.

    it('makes the request', function(done) {
        requestStub.yields(null, {statusCode: 200}, '{}');

        server.inject(options, function(response) {
            //arg[0] is url from request.get(url, function)
            var requestUrl = requestStub.getCall(0).args[0];

            expect(requestUrl).to.equal('http://date.jsontest.com');
            done();
        });
    });

    it('returns the date', function(done) {
        requestStub.yields(null, {statusCode: 200}, JSON.stringify({date: '02-17-2015'}));

        server.inject(options, function(response) {
            expect(response.statusCode).to.equal(200);
            expect(response.result).to.equal('02-17-2015');
            done();
        });
    })