如何使用 Node.js 和 Sinon 模拟 Mongo 光标对象

How to Mock Mongo Cursor object with Node.js and Sinon

我需要为一些旧代码添加单元测试覆盖率,并且难以创建模拟 Cursor object 允许链接项目、限制、跳过、toArray,如下所示。

collection.find({}, (err, res) => {
......
    const results = res.project(projection)
                       .limit(limitCount)
                       .skip(skipCount)
                       .toArray()

我之前用响应对象上可用的 toArray 模拟过 DB/collection/find(如下所示),但不确定如何处理上面提到的另一个游标 'values' 的链接。

            let fakeFind = () => {
                return {
                    toArray: () => {
                        return Promise.resolve(testCustomerRecord);
                    }
                };
            }

            let stubFind = sinon.stub().callsFake(fakeFind);
            
            let mockDb = {
                collection: () => {
                    return {
                        find: stubFind
                    };
                }
            };

我尝试将它们添加为属性、函数,但返回如下错误:

TypeError: item.project(...).limit 不是函数

欢迎任何建议!

stub.returnsThis(); 方法允许您存根链调用。

例如

import sinon from 'sinon';

// service under test
const service = {
  find(db) {
    return new Promise((resolve) => {
      db.collection.find({}, (err, res) => {
        const results = res.project({ a: 1 }).limit(10).skip(0).toArray();
        resolve(results);
      });
    });
  },
};

describe('68483854', () => {
  it('should pass', async () => {
    const mockRes = {
      project: sinon.stub().returnsThis(),
      limit: sinon.stub().returnsThis(),
      skip: sinon.stub().returnsThis(),
      toArray: sinon.stub().returns('mock data'),
    };
    const mockDb = {
      collection: {
        find: sinon.stub().callsFake((where, callback) => {
          callback(null, mockRes);
        }),
      },
    };
    const actual = await service.find(mockDb);
    sinon.assert.match(actual, 'mock data');
    sinon.assert.calledWithExactly(mockRes.project, { a: 1 });
    sinon.assert.calledWithExactly(mockRes.limit, 10);
    sinon.assert.calledWithExactly(mockRes.skip, 0);
    sinon.assert.calledOnce(mockRes.toArray);
  });
});