2012-10-27 15 views
5

私は試験をしているモジュールが必要とするpostgresへの呼び出しを模擬するためにsinonをどのように使うことができますか?可能。Node.jsのSinon.jsを使った単体テスト用のMocking

私はpostgresモジュール自体をテストしようとしておらず、オブジェクトが期待どおりに動作していることを確認し、このインスタンスで呼び出すべきものを呼び出しています。

私の問題は、ノードのセットアップが必要だと思います。私のモジュールではデータベースにヒットするためにpostgresモジュールが必要ですが、ここでは統合テストを実行したくありません。孤立して作業していて、実際にデータベースが何をしているか気にしないで、私はそれを私の統合テストに任せます。

モック/スタブ/フェイクを関数に送信し、その存在をテストし、必要なモジュール上でそれを使用しているかどうかを確認するオプションパラメータを設定する人がいますが、私には匂いがする(私はノードで新しいので、多分これはそうではない)。

私はこれを嘲笑して、それが可能であれば要求を乗っ取ろうとするよりも好きです。

いくつかのコード(私はTDDで実行しているとして、これは実際のコードではなく、 機能は本当に何もしない、関数名が実数である注意してください)

TESTのSETUP

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(); 
    }); 

これはそれPASSEと、それが失敗したPostgresのコネクタコードなしとして(私は思う)作品:二つの試験にも

問題は、失敗する必要があるときに100%を通過するスタブ(多分スパイ)を使用することになる2番目の方法です。そのため、私は午前中にそれを選択します。

アップデート2

私はデータベースに当たるものですclient.query方法をハイジャック、単に私のメソッドを実行し、それを強制するわけではない主な理由は、テストで100%満足していません結果を確認して行動をテストすることができますが、提案された改善点はありません。

私はスパイを使用してメソッドをキャッチし、ヌルを返し、メソッドが戻ってくるような行を含むフェードオブジェクトを返します。クエリの動作を追加すると変更されますが、ハードルを超えてしまいます。

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(); 
    }); 
+0

これは有効な接続が最初に必要であると思われます。つまり、ユニットテストを可能にする接続に応答するpostgresの実行中のインスタンスを意味します。 – Reinsbrain

+0

正直言って、私たちは管路を変更し、ポストグレを使用しないようにしましたが、これはちょっとはずれているかもしれませんが、正しく模倣したら、実行中のインスタンスは必要ありません、スタブ/スパイは接続として動作する必要があります。その基準でコードをテストすることができます。 – Modika

+0

私は先導的な貢献者であるbriancと連絡を取り合いました。彼は、pgへの差し迫った大きな変化があり、単体テストをはるかに簡単にすると述べています。この質問... – Reinsbrain

答えて

2

使用PG-プール: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のプール実装になるだろうし、シンクトンに依存しないので、モックがずっと簡単になる。うまくいけば助けて!

1

私は非常に明確に私の依存関係を置き換えます。それはおそらく最善の解決策ではありませんが、私が見た他のソリューションはそれほど素晴らしいものではありませんでした。

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

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

もう1つの解決方法は、モジュールファイルを文字列として読み込み、vmを使用してファイルを手動で読み込むことです。私がこれを調べると、複雑になることがわかったので、私は注射機能だけを使って行った。しかし、おそらくこのアプローチを検討する価値はあります。詳細はhereをご覧ください。

+0

返信、面白いアプローチのおかげで、私は可能な限り私のモジュールをできるだけきれいに保つために努力している、私は私が質問を更新した周りに仕事を見つけた、私につながる第2のテストマインドと別の問題。 – Modika

関連する問題