Node.js 使用sinon和mocha对pg promise进行存根

Node.js 使用sinon和mocha对pg promise进行存根,node.js,mocha.js,sinon,pg-promise,sinon-chai,Node.js,Mocha.js,Sinon,Pg Promise,Sinon Chai,假设我在下面的模块中有一个 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: con

假设我在下面的模块中有一个

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上运行一个单元测试,该测试将测试以“create”作为第一个参数,以“name”作为第二个参数调用db.func,但实际上不需要设置数据库连接(因此测试可以脱机运行)

据我所知,这就是像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
很可能是因为我对信农有限的接触


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

您可以通过禁用中的no
noLocking
选项来配置属性。这允许sinon替换以下属性:

const initOptions = { noLocking : true };
另一方面:

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

function create(name) {
      return db.func('create', name);
}
另外,
callsFake
接受一个函数,您正在给它一个承诺。使用
返回值

const dbStub = sinon.stub(db, 'func').returns(Promise.resolve(null))
设置
noLocking
选项时遇到问题。文档说明可以在初始化后设置它,但是如果我使用
db.$config.options.noLocking=true设置它,则会出现相同的错误。但是,如果我在database.js init选项中设置它,它可以正常工作

来自…的作者

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

我刚刚更新了报告以澄清这一点:

此选项是动态的(可以在初始化之前或之后设置)。但是,在库初始化后更改它不会影响已创建的数据库对象。

该对象的属性
func
是不可配置的,这意味着
sinon
不能用
对象替换该属性。定义属性
。这也是我从研究中可以得出的结论。然而,我想看看是否有任何其他的方式来做到这一点与pg承诺。你不能用pg Promise做离线单元测试,这不可能是真的谢谢你,这听起来是正确的解决方案!但是,我在设置取消锁定选项时遇到问题。文档声明可以在初始化后设置,但是如果我使用db.$config.options.noLocking=true设置,则会出现相同的错误。但是,如果我在database.js init选项中设置它,它可以正常工作。不过,在database.js模块中设置它并不是最佳选择。有什么想法吗?@MadsRC,老实说,我不知道,我认为你不太可能这样设置这个选项。一旦对象设置为不可配置,任何人都无法将其重置为可配置。@MadsRC,如果您的环境是开发的,您只能将该选项添加到init选项中。这样,在生产过程中,您仍然可以锁定它。这就是我实际上所做的!尽管我在测试中存根db.func以返回Promise.resolve(nulll)(正如您所建议的那样),但当我调用create时,db函数实际上仍然连接到数据库并创建(我在测试时碰巧有一个数据库监听localhost)。这是预期的行为,还是sinon.stub不应该覆盖create.js中引用的db.func?