Sinon 从中间件中取出模块的功能

Sinon stub out module's function from a middleware

基于,我还需要测试一个同样使用db-connection.js文件的中间件。中间件文件将如下所示:

const dbConnection = require('./db-connection.js')

module.exports = function (...args) {
   return async function (req, res, next) {
      // somethin' somethin' ...
      const dbClient = dbConnection.db
      const docs = await dbClient.collection('test').find()
 
      if (!docs) {
         return next(Boom.forbidden())
      }
   }
}

,数据库连接文件不改,即:

const MongoClient = require('mongodb').MongoClient
const dbName = 'test'
const url = process.env.MONGO_URL

const client = new MongoClient(url, { useNewUrlParser: true,
  useUnifiedTopology: true,
  bufferMaxEntries: 0 // dont buffer querys when not connected
})

const init = () => {
  return client.connect().then(() => {
    logger.info(`mongdb db:${dbName} connected`)

    const db = client.db(dbName)
  })
}

/**
 * @type {Connection}
 */
module.exports = {
  init,
  client,
  get db () {
    return client.db(dbName)
  }
}

中间件的工作原理是传递字符串列表(字符串是角色),我必须查询数据库并检查是否有每个角色的记录。如果记录存在,我将 return next(),而如果记录不存在,我将 return next(Boom.forbidden()) (下一个函数带有来自 Boom 模块的 403 状态代码) .

根据上面的细节,如果记录存在与否,如何测试中间件的return值呢?这意味着我必须准确断言 next()next(Boom.forbidden)

基于 。您可以为 reqres 对象和 next 函数创建存根。

例如(不运行,但应该可以。

const sinon = require('sinon');

describe('a', () => {
  afterEach(() => {
    sinon.restore();
  });
  it('should find some docs', async () => {
    process.env.MONGO_URL = 'mongodb://localhost:27017';
    const a = require('./a');
    const dbConnection = require('./db-connection.js');

    const dbStub = {
      collection: sinon.stub().returnsThis(),
      find: sinon.stub(),
    };
    sinon.stub(dbConnection, 'db').get(() => dbStub);
    const req = {};
    const res = {};
    const next = sinon.stub();
    const actual = await a()(req, res, next);
    sinon.assert.match(actual, true);
    sinon.assert.calledWithExactly(dbStub.collection, 'test');
    sinon.assert.calledOnce(dbStub.find);
    sinon.assert.calledOnce(next);
  });
});