mochaoose调用mocha测试功能

时间:2015-01-22 20:22:25

标签: node.js express mongoose mocha sinon

在对下面的代码进行单元测试时遇到一些问题,我不确定它是否可能由于它的编码方式。

  

storeModel.js

var storeSchema = new Schema({
    storeId : { type: String, index: true},
    storeName : String
});
var model = mongoose.model('store', storeSchema);

var findStoresById = function(ids, callback) {
    model.find({ storeId: { $in: ids }}, function (err, result) {
        if (err) callback(err);
        callback(err, result);
    });
};

return {
    findStoresById: findStoresById,
    schema: storeSchema,
    model: model
};}();

我测试的是这样..

it('will call "findStoresById" and return matched values [storeId: 1111] ', function (done) {

    storeModel.findStoresById(['1111'], function(err, store) {
        assert.equal(store[0].storeId, '1111');
        assert.equal(store[0].storeName, 'StoreName');
        assert.equal(err, null);
        done();
    });

});

但是当我在一个单独的函数中实现以下代码时出现问题:

get: function (req, res) {

    if (req.query.storeIds) {

        var ids = req.query.storeIds.split(',');

        storeModel.findStoresById(ids, function(err, stores) {
            if (err) {
                return res.send(err);
            }

            if (_.isEmpty(stores)) {
                var error = {
                    message: "No Results",
                    errorKey: "XXXX"
                }
                return res.status(404).json(error);
            }
            return res.json(stores);
        }); ...

我如何对此进行单元测试,我不想嘲笑它,因为" findStoreById"需要测试,还是需要重构?建议?

2 个答案:

答案 0 :(得分:4)

我认为你实际上应该抄袭findStoreById,因为不这样做get不能严格地进行单元测试,因为它不是孤立的,可能会因为没有自己的错。看作你想要测试的功能在于findStoreById的回调而不是方法本身,我们可以愉快地将它存根并使用sinon的yields方法来相应地调用它的回调。

请注意,如果您要测试路线,最好使用supertest,否则您手上会有大量的请求和响应方法模拟。因此,例如:

var request = require('supertest');
var express = require('express');
// stub database method
sinon.stub(storeModel, 'findStoresById');

// create a test app/route to which we direct test requests
var app = express();
app.get('/', myRouteFunction);

it('sends a 404 error when no stores are found', function(done) {
  // use the second argument of `yields` to pass a result to the callback
  storeModel.findStoresById.yields(null, []);
  request(app).get('/').expect(404, done);
});

it('responds with any stores found', function(done) {
  // pass an array of found stores to the callback
  storeModel.findStoresById.yields(null, [{_id: 1}]);
  request(app).get('/').end(function(err, res) {
    if(err) return done(err);

    assert.deepEqual(res.body, [{_id: 1}]);
    done();
  });     
});

答案 1 :(得分:2)

如果你想要的是测试某个Mongoose模型的static'smethod's,我建议你使用sinonsinon-mongoose

但首先,您的代码有一些提示

var storeSchema = new Schema({
    storeId : { type: String, index: true},
    storeName : String
});

// 1) If you will callback with the same 'err' and 'result', pass the callback directly
function findStoresById(ids, callback) {
  // Instead of this...
  this.find({ storeId: { $in: ids } }, function (err, result) {
      if (err) callback(err);
      callback(err, result);
  });

  // Use this... it's the same, but shorter
  this.find({ storeId: { $in: ids } }, callback);
}

// 2) Declare a static method on your model, instead of export manually (see Monggose documentation for more info)
storeSchema.static('findStoresById', function (ids, callback) {
});

// 3) Create your model after the statics were declared, and use CamelCase
var model = mongoose.model('Store', storeSchema);

// 4) Export just your model
// If you want the model -> var Store = mongoose.model('Store')
// If you want the schema -> var schema = Store.schema
// If you want to call your method -> Store.findStoresById(...)
module.exports = model;

然后,测试方法findStoresById

var sinon = require('sinon');
require('sinon-mongoose');

var Store = mongoose.model('Store');

sinon.mock(Store)
  .expects('find').withArgs({ storeId: { $in: ['id1', 'id2'] } })
  .yields(null, 'SUCCESS!');

Store.findStoresById(['id1', 'id2'], function (err, res) {
  assert(res, 'SUCCESS!');
});

您可以在sinon-mongoose repo。

上找到工作(和简单)示例