使用sinon和mocha

时间:2017-10-20 18:10:52

标签: node.js mocha sinon pg-promise sinon-chai

假设我有一个以下模块,如database.js

const initOptions = {}
const pgp = require('pg-promise')(initOptions)
const config = require('../../config')

const db = pgp({
  host: config.database.host,
  port: config.database.port,
  database: config.database.database,
  user: config.database.user,
  password: config.database.password
})

module.exports = db

以下模块为create.js

const db = require('./database')

function create (name) {
  return new Promise((resolve, reject) => {
      db.func('create', name)
      .then(data => {
        return resolve(data)
      })
      .catch(err => {
        return reject(err)
      })
  })
}

module.exports = create

我正在尝试在create.js上运行单元测试,测试db.func是以'create'作为第一个参数调用而'name'作为第二个参数调用,但实际上并不需要设置数据库连接(因此测试可以脱机运行)。

从我可以收集到的内容,这就是可以使用像sinon.JS这样的库,所以我尝试创建一个测试并将db对象存根。

const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')

chai.use(chaiAsPromised)

const sinon = require('sinon')

const expect = chai.expect

const create = require('./create.js')

describe('Test Module', () => {
  it('should test stuff', () => {
    const db = require('./database')
    const dbStub = sinon.stub(db, 'func').callsFake(Promise.resolve(null))
    expect(create('test').then).to.be.a('Function')
  })
})

然而,它失败了

TypeError: Cannot redefine property: func

很可能是由于我对sinon的接触有限......

我如何进行存根(或者我需要模拟?)db函数,以便我可以测试它并确保调用db.func?

1 个答案:

答案 0 :(得分:3)

您可以通过在.Net fiddle中使用no noLocking选项禁用锁定来配置属性。这允许sinon替换属性:

const initOptions = { noLocking : true };

在相关说明中:

你的create函数正在创建一个不必要的promise包装器,这是一个promise反模式。您应该只返回db.func的结果,这是一个承诺:

function create(name) {
      return db.func('create', name);
}

同样callsFake需要一个函数,你正在给它一个承诺。请改用returns

const dbStub = sinon.stub(db, 'func').returns(Promise.resolve(null))
  

我在设置noLocking选项时遇到问题。文档声明它可以在初始化后设置,但是如果我使用db.$config.options.noLocking = true设置它,则会发生相同的错误。但是,如果我在database.js init选项中设置它,它可以正常工作。

来自Initialization Options的作者......

这是因为此时noLocking只会影响任务和事务。由于协议的db级别仅启动一次,因此在库初始化后设置noLocking不会影响它。

我刚刚更新了pg-promise以澄清它: This option is dynamic (can be set before or after initialization). However, changing it after the library's initialization will not affect Database objects that have already been created.