4

假设我有以下模块,如 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 ?

4

1 回答 1

3

您可以通过在Initialization OptionsnoLocking中使用 no选项禁用锁来使属性可配置。这允许 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 初始化选项中设置它,它就可以正常工作。

来自pg-promise的作者...

这是因为那时noLocking只能影响任务和事务。并且由于db协议的层级只启动一次,noLocking所以在库初始化之后设置并不会影响它。

我刚刚更新了文档以澄清它: 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.

于 2017-10-20T18:47:27.183 回答