用Node.js中的Sinon.js嘲笑Postgres进行unit testing

我有困难得到我的头如何我可以使用sinon嘲笑postgres这是我正在testing的模块所需的,或者如果它甚至是可能的。

我不是试图testingpostgres模块本身,只是我的对象,以确保它按预期工作,而且它正在调用它应该在这种情况下调用。

我想这个问题是需要设置节点,因为我的模块需要postgres模块来打数据库,但在这里我不想运行一个集成testing,我只是想确保我的代码是孤立的工作,并不在乎数据库在做什么,我会把它留给我的集成testing。

我看到一些人设置他们的函数有一个可选的参数发送模拟/存根/假的function,testing它的存在,如果它在那里使用它在所需的模块,但这似乎像一个气味给我(我是新的节点,所以也许这不是)。

我宁愿嘲笑这一点,而不是尝试和劫持的要求,如果这是可能的。

一些代码 (请注意,这不是真正的代码,因为我使用TDD运行,并且该函数没有做任何事情,函数名称是真实的)

testing设置

describe('#execute', function () { it('should return data rows when executing a select', function(){ //Not sure what to do here }); }); 

示例function

 PostgresqlProvider.prototype.execute = function (query, cb) { var self = this; if (self.connection === "") cb(new Error('Connection can not be empty, set Connection using Init function')); if (query === null) cb(new Error('Invalid Query Object - Query Object is Null')) if (!query.buildCommand) cb(new Error("Invalid Query Object")); //Valid connection and query }; 

看起来有点像这样包装postgres模块有趣,但有一些devise,因为这个应用程序将有几个“提供者”,我想为他们公开相同的API,所以我可以交替使用它们。

UPDATE

我决定我的testing太复杂了,因为我正在查看连接调用是否已经完成,然后返回数据,这些数据对我产生了影响,于是我将其剥离并放到两个testing中:

模拟testing

 it('should call pg.connect when a valid Query object is parsed', function(){ var mockPg = sinon.mock(pg); mockPg.expects('connect').once; Provider.init('ConnectionString'); Provider.execute(stubQueryWithBuildFunc, null, mockPg); mockPg.verify(); }); 

这工作(我认为),因为没有postgres连接器代码它失败,通过(繁荣:))

现在问题是第二种方法,我将使用一个存根(也许是一个间谍),当它失败时通过100%,所以我会在早上select它。

更新2

我不是100%满意的testing,主要是因为我没有劫持client.query方法,它是命中数据库的方法,但只是我的执行方法,强制它的path,但它让我看到结果并坚决反对它来testing行为,但会对任何build议的改进开放。

我正在使用间谍来捕捉方法,并返回null和一个包含行的人造对象,就像方法会传回去一样,这个testing会随着我添加更多的查询行为而改变,但它会让我超越我的障碍。

  it('should return data rows when a valid Query object is parsed', function(){ var fauxRows = [ {'id': 1000, 'name':'Some Company A'}, {'id': 1001, 'name':'Some Company B'} ]; var stubPg = sinon.stub(Provider, 'execute').callsArgWith(1, null, fauxRows); Provider.init('ConnectionString'); Provider.execute(stubQueryWithBuildFunc, function(err, rows){ rows.should.have.length(2); }, stubPg); stubPg.called.should.equal.true; stubPg.restore(); }); 

使用pg-pool: https : //www.npmjs.com/package/pg-pool

无论如何,它将被添加到pg中,并据说使unit testing更容易(来自BrianC)( https://github.com/brianc/node-postgres/issues/1056#issuecomment-227325045 ):

签出https://github.com/brianc/node-pg-pool-它将在node-postgres中很快实现池实现,并不依赖于使嘲讽更容易的单例。 希望有帮助!

我非常明确地取代我的依赖。 这可能不是最好的解决scheme,但我看到的所有其他解决scheme都不是那么好。

 inject: function (_mock) { if (_mock) { real = _mock; } } 

您将此代码添加到testing中的模块。 在我的testing中,我将调用注入方法并replace实际的对象。 我之所以不100%喜欢它是因为你必须添加额外的代码只用于testing。

另一种解决scheme是将模块文件作为string读取,并使用vm手动加载文件。 当我调查这个时,我发现它有点复杂,所以我只是使用注入function。 尽pipe这个方法可能值得研究。 你可以在这里find更多的信息。