Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test Hapijs endpoint without hitting the db

I'm developing a restApi using Hapi js. The structure of the project is like the following:


   |-Root
      server.js
      |-router
         routes.js
      |-handlers
         authHandler.js
      |-db
         userDb.js
 

An authentication request would hit the routes.js and forwarded to authHandler.js which in turn calls userDb.js. userDb.js talk to a database and returns the result to authHandler.js which return the response to the client.

I've been trying write a test where the userDb.js doesn't talk to the database

For this i'm using Hapi's inject to be able to call the routes without actually starting the server. I'm struggling to figure out how to mock the database in the call chain so that I can supply a dummy response.

So in short, I want the userDb.js to be replaced by a mock when testing.

like image 972
sfabriece Avatar asked Sep 06 '14 22:09

sfabriece


1 Answers

After the suggestion from @AlbertZaccagni above, I consulted the documentation of sinon and I came up with the following:

NB: I have omittet some code that declares the routes and other non essential parts to the question at hand.

Assuming that userDb.js is the module that connects to the database, and that I want to mock the response from the database:

userDb.js looks like this:

var db = require(/*path to db */);

module.exports.getUser = function(id, callback){
    db.query('sql query', function(err, rows){
        if(err){
           return callback(err);
        }
        return callback(null, rows[0]);/*returns the first object- 
        in the resultset from the database.*/
    });
}

Inside my test folder I created a file called mytest.js with the following content:

//don't forget to install sinon JS via npm
var sinon = require('sinon');
var server = require(/*path to hapi server*/); 
var userDb = require(/*path to the module we are stubbing/mocking*/);

describe('Stub test', function(){
   var options = {};
    options.method = 'GET';
    options.url = '/user/1';

    it('with stubbing', function(done) {
        var stub = sinon.stub(userDb, 'getUser', function(id, callback) {
            if (id < 5) {
                return callback(null, 100);/*in this case i'm just testing 
                to see if this function
                will get called instead- 
                of the actual function. That's why 100.*/
            }

            return new Error('test error');
        });
        server.inject(options, function(res) {
            var result = res.result;
            res.statusCode.should.equal(200);
            result.num.should.equal(100);
            done();
        });
    });
});

When I run npm test on my working directory, I see that It passes without actually calling the database and it returns 100 for the username 1.

like image 178
sfabriece Avatar answered Sep 28 '22 05:09

sfabriece