How to test coded database queries

I have a Sails.Js controller that looks like this:

module.exports = {
  confirmID: function(req,res) {
    var uid = req.params.id;
     User.findOne({id:uid}).exec(function(err,user) {
       // ...
     });
  }
}

      

where User

is the sail-postgres model. I tried to test it with mocha, sinon and supertest with a test like this

describe('Controller', function() {
  var sandbox;

  before(function() {
    sandbox = sinon.sandbox.create();
    sandbox.stub(User, 'findOne');
  });

  after(function() {
    sandbox.restore();
  });

  describe('GET /confirmid/:id', function() {

    it('should do something', function(done) {
      request(sails.hooks.http.app)
        .get('/confirmid/123')
        .expect(200)
        .end(function(err,res) {
          sandbox.fakes[0].called.should.be.true;
          done();
        });
  });
});

      

If I leave it, it is an error because exec is called undefined, but I cannot stub the nested exec method without error or validation. Is there a way to stub a series of method calls like .find().exec()

? Or am I better off just leaving this for integration tests where I can test it with a real database?

+3


source to share


3 answers


Assuming you really want to stub (and not just spy) - you want to control what the request allows, not just know if the request has been fulfilled. Here I am using the stub / waterline request methods . Something like...

var stubQueryMethod = require('stubQueryMethod');

describe('Controller', function() {
  before(function() {
    stubQueryMethod(User, 'findOne', {
      id: 123,
      name: 'Fred Fakes'
    });
  });

  after(function() {
    User.findOne.restore();
  });

  describe('GET /confirmid/:id', function() {
    it('should do something', function(done) {
      request(sails.hooks.http.app)
        .get('/confirmid/123')
        .expect(200)
        .end(function(err,user) {
          user.should.have.property('name', 'Fred Fakes');
          done();
        });
    });
  });
});

      



Source: https://gist.github.com/wxactly/f2258078d802923a1a0d

+3


source


For people looking for other options for stubbing or modeling waterline models, I found the following four options:

After evaluating each one, I decided to use sails-mock-mock because it is easy to understand and seems to be the most used sails mock library according to npm: https://www.npmjs.com/package/sails-mock -models



Hope this helps someone!


Update: I am still using sails-mock-models and it is quite simple, but there are a few disadvantages, for example it does not return promises which are taken in q.all (promArray). then () call. If I do research for other options or find a workaround, I'll post it here.

+2


source


This will only work for queries that use exec

, and it overloads all calls exec

, so if you try to return an error and you have, say, a controller with a policy, front and policy makes the database you will probably run into an error there before of how to push the controller code you wanted to test ... which can be fixed with stub.onCall(x)

, but is still a little dangerous.

Caveats aside, this is how I've done it in the past:

var path = require('path');
var sinon = require('sinon');

var Deferred = require(path.join(
  process.cwd(),
  'node_modules/sails',
  'node_modules/waterline',
  'lib/waterline/query/deferred'
));

module.exports = function () {
  return sinon.stub(Deferred.prototype, 'exec');
};

      

Assuming you have the following service, MyService:

module.exports.dbCall = function (id, cb) {

  Model.findOne(id).exec(function (err, result) {

    if (err) {
      sails.log.error('db calls suck, man');
      return cb(err, null);
    }

    cb(null, result);

  });

};

      

You can test the error case like this:

before(function () { 
  stub = databaseStub(); 
});

afterEach(function () { 
  stub.reset();
});

after(function () {
  stub.restore(); 
});

it('should return errors', function (done) {

  stub.onCall(0).callsArgWith(0, 'error');

  MyService.dbCall(1, function (err, results) {
    assert.equal(err, 'error');
    assert.equal(results, null);
    done();
  });

});

      

0


source







All Articles