如何将一个Node.js MongoDB链接fn调用存根以模拟我的最终结果?

时间:2017-05-01 22:58:14

标签: javascript node.js unit-testing sinon stub

我正在尝试使用Sinon.JS Stubs测试(使用Node.js MongoDB driver)以下调用...

collection.find({mood: 'happy'}).toArray((err, result) => {

  // array result

  cb(null, result);
});

我在这里挂起的是.toArray() 链式功能。上述调用会将result作为预期的Array返回。

为了证明我的斗争 - 并且与之形成鲜明对比 - 我能够存储下面的链接的调用......

collection.findOne({id: 'id'}, (err, result) => {

    // single result

    cb(null, result);
  });

stubb' d =>

findOneStub.yields(null, {username: 'craig'});

是否有一种简单的方法来存储我的.find调用,该调用返回一个带有.toArray的函数,最终模拟我的结果?

1 个答案:

答案 0 :(得分:2)

当我想要使用Mongo驱动程序案例来复制嵌套对象的方法时,我通常会做的是模拟一个模仿调用链的对象,如下所示:

使用回调

对toArray()进行存根
let mockDbCollection = {
  find: function() {
    return {
      toArray: function(cb) {
        const results = [{
          username: 'craig'
        }];

        cb(null, results);
      }
    };
  }
};

sinon.stub(db, 'collection')
  .returns(mockDbCollection);

db.collection('users').find({
  id: 'id'
}).toArray((err, docs) => {
  console.log(docs);
  done();

});

使用promise

对toArray()进行存根
let mockDbCollection = {
  find: function() {
    return {
      toArray: function() {
        return Promise.resolve([{
          username: 'craig'
        }]);
      }
    };
  }
};

sinon.stub(db, 'collection')
  .returns(mockDbCollection);

db.collection('messages').find({
  id: 'id'
}).toArray().then((docs) => {
  console.log(docs);
  done();
});

此范例可用于您想要模拟复杂对象上的一系列调用的任何情况,仅关注链中最后一个调用的响应。您可以根据需要尽可能深入地进行操作。

如果你想要更高级的东西,如设置存根的行为或计算调用等,你可以在这个article中找到一些其他技术。作者展示了一些使用复杂DOM对象的例子。

根据我们示例中的教程调整技术,我们可以轻松地执行以下操作:

// here we stub the db.collection().findOne() method
// and fabricate a response
let stubFindOne = this.sandbox.stub().resolves({
  _id: 'id'
});

// now, we can set the stub 
// function in our mock object
let mockDb = {
  collection: () => {
    return {
      findOne: stubFindOne
    };
  }
};

通过这种方式,我们可以像往常一样操纵和检查存根方法,例如

const args = stubFindOne.firstCall.args;

将返回第一个调用的参数列表等。