javascript - 使用Sinon的Mongoose模型的 stub 保存实例方法

标签 javascript node.js unit-testing mongoose sinon

我正在尝试使用 Mongoose 模型测试用于保存小部件的服务功能。我想在我的模型上 stub 保存实例方法,但我想不出一个好的解决方案。我看过其他建议,但似乎都不完整。

见... this , 和 this .

这是我的模型...

// widget.js

var mongoose = require('mongoose');

var widgetSchema = mongoose.Schema({
    title: {type: String, default: ''}
});

var Widget = mongoose.model('Widget',  widgetSchema);

module.exports = Widget;

这是我的服务...

// widgetservice.js

var Widget = require('./widget.js');

var createWidget = function(data, callback) {

    var widget = new Widget(data);
    widget.save(function(err, doc) {
        callback(err, doc);
    });

};

我的服务很简单。它接受一些 JSON 数据,创建一个新的小部件,然后使用“保存”实例方法保存小部件。然后它会根据保存调用的结果回调传递 err 和 doc。

我只想在调用 createWidget({title: 'Widget A'}) 时进行测试...

  • 使用我传递给服务函数的数据调用一次 Widget 构造函数
  • 新创建的小部件对象上的保存实例方法被调用一次
  • 额外的信用:保存实例方法用 null 回调错误,用 {title: 'Widget A'} 回调文档。

为了单独测试,我可能需要...

  • 模拟或 stub Widget 构造函数,以便它返回一个我在测试中创建的模拟小部件对象。
  • stub 模拟小部件对象的保存函数,以便我可以控制发生的情况。

我无法弄清楚如何使用诗乃做到这一点。我尝试了在 SO 页面上找到的几种变体,但都没有运气。

注意事项:

  • 我不想将已构建的模型对象传递给服务,因为我希望服务成为唯一“了解” Mongoose 的事物。
  • 我知道这不是最重要的事情(只是通过更多的集成或端到端测试来测试它,但找出解决方案会很好。

感谢您提供的任何帮助。

最佳答案

如果要测试它,这就是我的处理方法,首先有一种方法可以将我的模拟小部件注入(inject)到小部件服务中。我知道有node-hijack , mockery或类似 node-di ,他们都有不同的风格,我相信还有更多。选择一个并使用它。

一旦我做对了,我就用我的模拟小部件模块创建我的小部件服务。然后我做这样的事情(这是使用mocha顺便说一句):

// Either do this:
saveStub = sinon.stub();
function WidgetMock(data) {
    // some mocking stuff
    // ...
    // Now add my mocked stub.
    this.save = saveStub;
}


// or do this:
WidgetMock = require('./mocked-widget');
var saveStub = sinon.stub(WidgetMock.prototype, 'save');


diInject('widget', WidgetMock); // This function doesn't really exists, but it should
// inject your mocked module instead of real one.

beforeEach(function () {
    saveStub.reset(); // we do this, so everytime, when we can set the stub only for
    // that test, and wouldn't clash with other tests. Don't do it, if you want to set
    // the stub only one time for all.
});
after(function () {
    saveStub.restore();// Generally you don't need this, but I've seen at times, mocked
    // objects clashing with other mocked objects. Make sure you do it when your mock
    // object maybe mocked somewhere other than this test case.
});
it('createWidget()', function (done) {
    saveStub.yields(null, { someProperty : true }); // Tell your stub to do what you want it to do.
    createWidget({}, function (err, result) {
        assert(!err);
        assert(result.someProperty);
        sinon.assert.called(saveStub); // Maybe do something more complicated. You can
        // also use sinon.mock instead of stubs if you wanna assert it.
        done();
    });
});
it('createWidget(badInput)', function (done) {
    saveStub.yields(new Error('shhoo'));
    createWidget({}, function (err, result) {
        assert(err);
        done();
    });
});

这只是一个示例,我的测试有时会变得更复杂。大多数时候,我想模拟的后端调用函数(这里是widget.save)是我希望它的行为随着每个不同的测试而改变的函数,所以这就是我每次重置 stub 的原因.

这也是做类似事情的另一个例子:https://github.com/mozilla-b2g/gaia/blob/16b7f7c8d313917517ec834dbda05db117ec141c/apps/sms/test/unit/thread_ui_test.js#L1614

关于javascript - 使用Sinon的Mongoose模型的 stub 保存实例方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22340419/

相关文章:

c++ - 在 Catch2 中指定外部文本文件路径的最佳方式

javascript - 重复的表单字段输入

database - 环回: Cannot find module 'negotiator'

node.js - 一个请求中的多个查询

c# - Rhino 模拟,VerifyAllExpectations

php - Selenium 浏览器窗口大小

javascript - 切换类以选择带 Angular 报价

javascript - 添加谷歌支付到 Adyen Web SDK

javascript - document.onmouseover 和 onmouseout 事件参数在 IE 8 和 IE7 中未定义

JavaScript 日期对象在浏览器中包含 "T"字符,但在 MongoDB 中不包含