2009-07-14 22 views
21

私のC++コードを単体テストできるようにするために、私は通常、テスト中のクラスのコンストラクタを "実動コード"または擬似/モックオブジェクトのいずれかにすることができますこれらの注入オブジェクト)。私はどちらでもこれを行ったC++の依存関係注入のためのテンプレート

  1. "プロダクションコード"クラスと偽/モッククラスの両方が継承するインターフェイスを作成します。
  2. テスト対象のクラスを、テンプレートパラメータとして注入オブジェクトの型とコンストラクタへのパラメータとしての注入オブジェクトのインスタンスをとるテンプレートクラスにします。

いくつかのランダムな思考:

  • は、我々は概念を(C++ 0xの)持ってまで、唯一のドキュメントとパラメータの命名は、(テンプレートを使用している場合)、テスト中のクラスを提供するために、どのようなヒントします。
  • これは、レガシーコードのためのインタフェースを作成することができるとは限らない
  • インタフェースは基本的に、同じようにして、依存性注入
  • を行うことができるように作成され
  • :テスト対象のクラスには、依存性注入を可能にするためだけに行われるテンプレート

あなたの考えは?この問題の他の解決策はありますか?

答えて

4

私はインターフェイスオプションが優れていると思いますが、テスト用に共通の基本クラスを作成する必要はありません。プロダクションクラスからモッククラスを継承し、必要なメソッドをオーバーライドすることができます。メソッドを仮想的にする必要がありますが、それはmockppのようなツールがどのように機能し、このプロセスを少しでも自動化することができます。

+0

これはとても単純ですが、本当に強力です。私はそれが好きです! –

+4

ちょうど記録のために、メソッドは仮想(非仮想インターフェイス(NVI)イディオムを参照してください)に問題があることを認識する必要があります –

+1

はい、時にはこのアプローチは "純粋なNVI"と競合することがあります。多くの場合、保護された仮想関数だけを嘲笑することで逃げることができますが、公開されている非仮想インタフェースを模倣する必要がある場合は、公開仮想化してNVIを使用するにはあまりにも害を与えません。このケースでは、ベストプラクティスのコンパイラー強制が失われますが、ベストプラクティス自体は失われます。 –

8

C++の場合、実際のクラスと同じ名前をモッククラスに渡します。単体テストをリンクするときは、実際のものではなくモックオブジェクト/ライブラリファイルとリンクしてください。

+1

理論上はい。しかし、私はそれが実際には良いとは思わない。例えば。 1つのテストで模擬したいクラスは別のテストでテストされることがあります。次に、すべてのテストスイートまたはそのようなものについて、個別のプロジェクト(VSプロジェクトなど)を作成する必要があります。 –

+1

かなり大丈夫です。私は、テストフレームワークにのみ対応するために、重要なコード変更(インターフェイスやDIは実際のポイントがない場合でもどこでも)に対して非常に強い反感を持っています。いずれにしても、このスキームは実用的に動作します(実際には実働環境で正常に使用されていることがわかりました)。しかし、少なくともコード自体には含まれていません。 –

+0

私は同意します。私はそれがどのような結果をもたらすのかについて何らかの調査をしなくてはなりません。おそらく、いくつかの魔法をVSプロジェクトに適用して、それをより簡単にすることができます。 –

3

テンプレートは、この目的のために、私はと思いランタイムのわずかに低いパフォーマンスの低下(以下間接、以下の呼び出し、よりインライン最適化を)持っていますが、あなたはコンパイル時間のための非常に高いペナルティを受けるようになります...

(ボトルネックコード)を遅くすることができない場合を除いて、インタフェースはより良い(我々がC++ 0x TR1の概念を持つまで)。インタフェースは、実行時により動的で切り替え可能です。

デフォルトの注入オブジェクト(実際のもの)を使ってクラスを構築できますが、テストでモックを注入するファクトリを持つことができます。サブクラス化する必要はありません。

+1

最後の段落について詳しく説明できますか?どのようにモックオブジェクトを注入するために工場を使用しますか? –

+0

http://msdn.microsoft.com/en-us/magazine/cc163739.aspx –

+1

要約:必要な内部オブジェクトをすべて作成するシングルトンファクトリを持つことができます。このファクトリを、モックを作成するファクトリに置き換えることができますあなたのテストのオブジェクト –

2

それは場合に役立ちますか分からないのですが、あなたはテンプレートのコンストラクタを持つことができます。

struct Class_Under_Test 
{ 
    template <typename Injected> 
    Class_Under_Test() 
    { 
     ... 

    // and even specialize them 
    template <> 
    Class_Under_Test <A_Specific_Injection_Class> 
    { 
     ... 

実際に使用されている一方だけが含まれます。

関連する問題