【问题标题】:Stubbing a Mongoose model with Sinon使用 Sinon 对 Mongoose 模型进行 Stub
【发布时间】:2012-07-04 08:39:25
【问题描述】:

我想为特定模型中的 Mongoose save 方法创建一个存根,以便我创建的模型的任何实例都将调用存根而不是普通的 Mongoose save 方法。我的理解是,这样做的唯一方法是像这样对整个模型进行存根:

var stub = sinon.stub(myModel.prototype);

不幸的是,这行代码导致我的测试抛出以下错误:

TypeError: Cannot read property 'states' of undefined

有人知道这里出了什么问题吗?

【问题讨论】:

    标签: node.js mongoose sinon


    【解决方案1】:

    而不是整个对象,试试:

    sinon.stub(YOURMODEL.prototype, 'save')
    

    确保 YOURMODEL 是类而不是实例。

    【讨论】:

    • save 在 Mongoose 的实例上。
    【解决方案2】:

    有两种方法可以做到这一点。第一个是

    var mongoose = require('mongoose');
    var myStub = sinon.stub(mongoose.Model, METHODNAME);
    

    如果您在控制台登录 mongoose.Model,您将看到模型可用的方法(特别是这不包括 lte 选项)。

    另一种(特定于模型的)方式是

    var myStub = sinon.stub(YOURMODEL.prototype.base.Model, 'METHODNAME');
    

    同样,存根也可以使用相同的方法。

    编辑:一些方法,如保存,如下所示:

    var myStub = sinon.stub(mongoose.Model.prototype, METHODNAME);
    var myStub = sinon.stub(YOURMODEL.prototype, METHODNAME);
    

    【讨论】:

    • 这对链式查询有什么作用?类似MYMODEL.findOne(...).where(...).gt(...).exec(callback)
    • @Milovan Zogovic 在下面看到我的答案
    • 对于静态方法:var myStub = sinon.stub(MYMODEL.schema.statics, STATICNAME);,如果有人感兴趣的话。很好的答案,@Jacob——console.log 的建议对我帮助很大
    • 值得注意的是,存根save()(存根通用Model原型)的第一个选项似乎不再适用于猫鼬(猫鼬版本4.11)。自定义模型的存根原型似乎仍然有效。
    【解决方案3】:

    看看sinon-mongoose。您可以期望只有几行代码的链式方法:

    sinon.mock(YourModel).expects('find')
      .chain('limit').withArgs(10)
      .chain('exec');
    

    您可以在 repo 上找到工作示例。

    另外,一个建议:使用mock 方法而不是stub,这将检查该方法是否真的存在。

    【讨论】:

    • 这取决于代码是如何编写的,而不是代码在做什么?无论调用是否在被测代码中链接,测试都应该是有效的。
    • 应该可以。但如果不这样做,请发布一个例子:)
    • 这不适用于保存方法。这就是海报要求嘲笑的方法。
    【解决方案4】:

    save 不是模型上的方法,而是文档(模型的实例)上的方法。声明here in mongoose docs

    构建文档

    文档是我们模型的实例。创建它们并保存到数据库很容易

    因此,如果您使用您的模型来模拟 save(),它将始终是未定义的

    按照@Gon 的回答,使用sinon-mongoosefactory-girlAccount 是我的模型:

    不会工作

    var AccountMock = sinon.mock(Account)
    
    AccountMock
      .expects('save') // TypeError: Attempted to wrap undefined property save as function
      .resolves(account)
    

    工作

    var account = { email: 'sasha@gmail.com', password: 'abc123' }
    
    Factory.define(account, Account)
    Factory.build('account', account).then(accountDocument => {
      account = accountDocument
    
      var accountMock = sinon.mock(account)
    
      accountMock
        .expects('save')
        .resolves(account)
    
      // do your testing...
    })
    

    【讨论】:

    • 在网上寻找一个与 sinon-mongoose 兼容的答案,谢谢。
    【解决方案5】:

    相切相关,但相关...

    我需要模拟一个自定义模型方法,例如:

    myModelSchema.methods.myCustomMethod = function() {....}
    

    我创建了一个存根:

    myCustomMethodStub = sinon.stub(MyModel.schema.methods, 'myCustomMethod').callThrough();
    

    【讨论】:

      【解决方案6】:

      正如 djv 所说,save 方法在文档上。所以你可以这样存根:

      const user = new User({
            email: 'email@email.com',
            firstName: 'firstName',
            lastName: 'lastName',
            userName: 'userName',
            password: 'password',
          });
      
      stub(user, 'save').resolves({ foo: 'bar' });
      

      奖励,你可以用 ChaiChai as promised 这样声明它:

      const promise = user.save();
      await chai.assert.doesNotBecome(promise, { foo: 'bar' });
      

      【讨论】:

        猜你喜欢
        • 2015-12-11
        • 2018-07-19
        • 2015-03-30
        • 2017-07-11
        • 2023-04-01
        • 2019-09-26
        • 1970-01-01
        • 2015-08-21
        相关资源
        最近更新 更多