Mongoose模型与Sinon的存根保存实例方法

2023-11-24

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

See... this, and 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 数据,创建一个新的小部件,然后使用“save”实例方法保存该小部件。然后它根据保存调用的结果回调传递错误和文档。

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

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

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

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

我不知道如何与诗农一起做这件事。我尝试了在 SO 页面上找到的几种变体,但没有成功。

NOTES:

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

感谢您的任何帮助,您可以提供。


如果要测试它,这就是我的方法,首先有一种方法将我的模拟小部件注入小部件服务。我知道有节点劫持, mockery或者类似的东西node-di,他们都有不同的风格,我相信还有更多。选择一个并使用它。

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

// 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)是我希望它的行为随着每个不同的测试而改变的函数,所以这就是为什么我每次都重置存根。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mongoose模型与Sinon的存根保存实例方法 的相关文章

随机推荐