如何测试存根数据库查询

时间:2014-09-12 01:19:29

标签: node.js orm sails.js sinon

我有一个看起来像这样的Sails.Js控制器

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

其中User是sails-postgres模型。我尝试用mocha,sinon和supertest测试它,并进行类似的测试

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();
        });
  });
});

如果我把它留在那里它会出错,因为exec是在undefined上调用的,但是我似乎无法在没有错误或测试挂起的情况下存根嵌套的exec方法。有没有办法存根一系列方法调用,如.find().exec()?或者我最好将其留给集成测试,我可以用实际的数据库进行测试吗?

3 个答案:

答案 0 :(得分:3)

假设您确实想要存根(不仅仅是间谍) - 您希望控制查询解析的内容,而不是简单地知道查询是否已执行。这是我用stub sails/waterline query methods的内容。有点像...

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();
        });
    });
  });
});

来源:https://gist.github.com/wxactly/f2258078d802923a1a0d

答案 1 :(得分:2)

对于寻找其他选项来存根或模拟水线模型的人,我发现了以下四个选项:

在对每一个进行评估之后,我决定使用 sails-mock-models ,因为它很容易理解,并且似乎是最常用的根据npm模拟库的风帆:https://www.npmjs.com/package/sails-mock-models

希望这有助于某人!

更新:我仍然使用sails-mock-models,这很容易,但是有一些缺点,例如它无法返回被带入q.all(promiseArray)的promise。然后()打电话。如果我到处调查其他选项或找到解决方法,我会在这里发布。

答案 2 :(得分:0)

这仅适用于使用exec的查询,并且它会重载所有exec次调用,因此如果您尝试返回错误,并且您拥有一个具有策略的控制器,并且策略执行数据库查找,您可能会在遇到要测试的控制器代码之前发生错误....可以使用stub.onCall(x)修复,但它仍然有点不稳定。

除了警告,以下是我过去做过的事情:

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');
};

假设您有以下服务,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);

  });

};

您可以像这样测试错误情况:

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();
  });

});