11

テストしているモジュールで必要なpostgresへの呼び出しをモックするためにsinonを使用する方法、またはそれが可能であるかどうかについて頭を悩ませています。

私はpostgresモジュール自体をテストしようとはしていません。それが期待どおりに機能していること、そしてこのインスタンスで呼び出すべきものを呼び出していることを確認するためのオブジェクトだけです。

問題はノードのセットアップが必要なことだと思います。私のモジュールではpostgresモジュールがデータベースにアクセスする必要がありますが、ここでは統合テストを実行したくありません。コードが分離して機能していることを確認したいだけです。データベースが何をしているのかは気にしないので、統合テストに任せます。

モック/スタブ/フェイクを関数に送信し、その存在をテストし、存在する場合は必要なモジュールで使用するためのオプションのパラメーターを持つように関数を設定する人を見たことがありますが、それは私には匂いのようです(私はノードで新しいので、多分これはそうではありません)。

可能であれば、requireをハイジャックするのではなく、これをモックアウトしたいと思います。

いくつかのコード(私は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を公開して、それらを交換して使用できるようにするため、いくつかの設計があります。

アップデート

私は、接続呼び出しが行われたかどうかを確認し、データを返すので、テストが複雑すぎると判断しました。そのため、データを取り除いて2つのテストに入れました。

模擬試験

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コネクタコードがないと失敗し、合格すると(ブーム:))機能します

問題は2番目の方法です。これは、失敗するはずのときに100%通過するスタブ(おそらくスパイ)を使用するので、午前中にそれを取得します。

アップデート2

私はテストに100%満足していません。これは主に、データベースにアクセスするclient.queryメソッドを乗っ取っているのではなく、executeメソッドをハイジャックしてパスに強制しているためですが、結果を確認できます。動作をテストするためにそれに対して主張しますが、提案された改善を受け入れるでしょう。

私はスパイを使用してメソッドをキャッチし、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();
    });
4

2 に答える 2

2

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

とにかくpgに追加されようとしており、(モック)ユニットテストが簡単になると言われています... BrianC(https://github.com/brianc/node-postgres/issues/1056#issuecomment-227325045)から:

チェックアウトhttps://github.com/brianc/node-pg-pool-すぐにnode-postgresでのプールの実装になり、モッキングをはるかに簡単にするシングルトンに依存しません。うまくいけば、それが役立ちます!

于 2016-06-21T15:38:50.870 に答える
1

依存関係を明示的に置き換えます。それはおそらく最良の解決策ではありませんが、私が見た他のすべての解決策もそれほど素晴らしいものではありませんでした。

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

このコードをテスト対象のモジュールに追加します。私のテストでは、injectメソッドを呼び出して、実際のオブジェクトを置き換えます。私が100%好きではない理由は、テストのためだけにコードを追加する必要があるからです。

もう1つの解決策は、モジュールファイルを文字列として読み取り、vmを使用してファイルを手動でロードすることです。これを調べたところ、少し複雑であることがわかったので、注入機能を使用するだけで済みました。ただし、このアプローチを調査することはおそらく価値があります。詳細については、こちらをご覧ください。

于 2012-10-27T19:29:48.980 に答える