在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