我如何存根 Node.js MongoDB 链式 fn 调用来模拟我的最终结果?

How can I stub a Node.js MongoDB chained fn call to mock my end result?

我正在尝试测试(Sinon.JS Stubs) the following call with the Node.js MongoDB driver...

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

  // array result

  cb(null, result);
});

让我挂在这里的是 .toArray() chained 函数。上面的调用 returns result 正如预期的那样 Array.


为了证明我的努力 - 并进行对比 - 我能够对以下 链接的调用进行存根...

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

    // single result

    cb(null, result);
  });

stubb'd =>

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

有没有直接的方法来存根我的 .find 调用,returns 一个带有 .toArray 的函数来最终模拟我的结果?

当我想像 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;

会return第一次调用的参数列表等