在Node.js中使用Sinon.js模拟Postgres进行单元测试
我无法理解我的头脑如何使用sinon来模拟我正在测试的模块所需的postgres调用,或者甚至可能。
我不是试图测试postgres模块本身,只是我的对象来确保它按预期工作,并且它正在调用它在此实例中应该调用的内容。
我想这个问题是节点的需求设置,因为我的模块需要postgres模块来访问数据库,但在这里我不想运行集成测试,我只是想确保我的代码独立工作,并不在乎数据库在做什么,我会把它留给我的集成测试。
我已经看到一些人设置他们的函数有一个可选参数来发送模拟/存根/假的功能,测试其存在,如果它在那里使用它在所需的模块,但这似乎像一个气味给我(我是新的节点,所以也许这不是)。
我更愿意嘲笑这一点,而不是试图劫持这个要求,如果可能的话。
一些代码 (请注意,这不是真正的代码,因为我使用TDD运行并且该函数没有做任何事情,函数名称是真实的)
测试设置
describe('#execute', function () {
it('should return data rows when executing a select', function(){
//Not sure what to do here
});
});
样本功能
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模块,但有一些设计,因为这个应用程序将有几个“提供者”,我想为他们公开相同的API,所以我可以互换使用它们。
UPDATE
我决定我的测试太复杂了,因为我正在查看连接调用是否已经完成,然后返回数据,这些数据对我产生了影响,于是我将其剥离并放入两个测试中:
模拟测试
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%,所以我会在早上选择它。
更新2
我对这个测试并不满意,主要是因为我没有劫持client.query方法,它是命中数据库的方法,而只是我的执行方法并强制它的路径,但它使我能够看到结果并坚决反对它来测试行为,但会对任何建议的改进开放。
我使用间谍来捕获方法并返回null和包含行的人造对象,就像方法会返回一样,这个测试会随着添加更多查询行为而发生变化,但它会让我跨越障碍。
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中,并据称使单元测试(嘲弄)变得更容易......来自BrianC(https://github.com/brianc/node-postgres/issues/1056#issuecomment-227325045):
Checkout https://github.com/brianc/node-pg-pool-它很快就会成为node-postgres中的池实现,并且不依赖于使嘲讽更容易的单例。 希望这有助于!
我非常明确地取代我的依赖。 这可能不是最好的解决方案,但我看到的所有其他解决方案都不是那么好。
inject: function (_mock) {
if (_mock) { real = _mock; }
}
您将此代码添加到测试中的模块。 在我的测试中,我调用注入方法并替换真实的对象。 我之所以没有100%喜欢它,是因为你必须为测试添加额外的代码。
另一种解决方案是将模块文件读取为字符串,并使用vm手动加载文件。 当我调查这个时,我发现它有点复杂,所以我只用了注入函数。 尽管如此,这可能是值得研究的。 您可以在这里找到更多信息。
链接地址: http://www.djcxy.com/p/11341.html上一篇: Mocking Postgres for unit tests with Sinon.js in Node.js
下一篇: type inference in argument list in combination with setter not working