带有猫鼬调用的摩卡测试功能

Posted

技术标签:

【中文标题】带有猫鼬调用的摩卡测试功能【英文标题】:mocha test function with mongoose call 【发布时间】:2015-03-21 18:56:43 【问题描述】:

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

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”中有需要测试的功能,或者是否需要重构?建议?

【问题讨论】:

我不明白为什么你的架构文件中需要这个return findStoresById: findStoresById, schema: storeSchema, model: model ;();。您可以在架构定义中将findStoresById 函数定义为静态函数,并在您可以访问它的模型的任何地方调用它。 storeSchema 也可以作为模型的属性访问。 你能给我举个例子吗? 【参考方案1】:

我反对你实际上应该存根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();
  );     
);

【讨论】:

我无法让 stub.yields 与 supertest 一起正常工作,它会跳过我的模拟并在我的代码中使用实际方法。这就是说我仍然可以用 supertest 很好地测试它就好了.. 但也许你可能知道为什么测试没有使用我的存根? 没有看到您的代码,我不确定为什么存根不起作用。将它与 supertest 结合使用应该不会有什么不同。【参考方案2】:

如果您想要测试某些猫鼬模型的static'smethod's,我建议您使用sinon 和sinon-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 存储库中找到工作(和简单)示例。

【讨论】:

非常感谢贡!今天对我有帮助

以上是关于带有猫鼬调用的摩卡测试功能的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何与摩卡和猫鼬一起使用?

Mocha/Sinon 测试猫鼬里面的快递

摩卡——手表和猫鼬模型

无论如何都超过了摩卡超时

带有 .validate() 的摩卡测试模式不返回

摩卡在测试后没有退出