使用sinon和mocha来保存pg-promise

假设我有一个以下模块,作为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上运行一个unit testing,它将testingdb.func是以'create'作为第一个参数,'name'作为第二个而调用的,但实际上并不需要build立数据库连接(所以testing可以离线运行)。

从我可以收集,这是什么库像sinon.JS可以用于,所以我试图创build一个testing,并残存的数据库对象。

 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函数,以便我可以testing它确保db.func被调用?

您可以通过在初始化选项中使用 no noLocking选项禁用锁来使属性可configuration。 这允许sinonreplace属性:

 const initOptions = { noLocking : true }; 

相关说明:

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

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

callsFake需要一个function,你给它一个承诺。 改用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. 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.