2016-07-28 3 views
0

、私はA::requestが呼び出されたとき、B::response()も同様に呼ばれていることを確認するために、ユニットテストclass Aにしたい:Google Test Framework:シャドーイングまたはバーチャルメソッドを使用する方が良いですか?以下の例では

class A 
{ 
public: 
    void request() 
    { 
     m_b.response(); 
    } 

private: 
    B m_b; 
}; 

class B 
{ 
public: 
    void response(); 
}; 

それを行うためには、class Bを嘲笑する必要があります。

class MockB : public B 
{ 
public: 
    MOCK_METHOD0(response, void()); 
}; 

テストが含まれるように:

class TestA : public A 
{ 
    ... 
}; 

... 
EXPECT_CALL(m_b, response()).Times(1); 
request(); 
... 

質問I s:B m_bの代わりにMockBを「注入する」方法は?

まずtecniqueclass MockBへのメソッド呼び出しをリダイレクトするShadowBクラスを作成します。これには、元のコードを外部バイナリに入れる必要がありますが、実際のコードを変更する必要はありません。

第tecnique

  • B::responsevirtual
  • 作るstd::unique_ptr<B> m_b
  • B m_bの変更は、テストセットアップ

第二のアプローチのMEAの間class MockBのインスタンスとm_b値を置き換えますより多くのコードが変更され、そのプロについてはわかりません。

答えて

1

問題を解決する正しい方法は2番目の方法です。より一般的には、ユニットテストコードを考慮して設計されていないコンポーネントにユニットテストコードを「レトロフィット」することは非常に難しく、ほとんどの場合、テストするコードを大幅に変更する必要があります。

モックコールバックオブジェクトを実際のものに置き換える仮想関数を使用すると、共通のインターフェースから継承することは非常に一般的なアプローチです。もう1つの選択肢は、テスト対象のクラスをテンプレートクラスにし、テンプレートパラメータをMockオブジェクトで置き換えることです。

+0

基本的に、テスト駆動型の設計手法を提案しています。非常に興味深いテンプレートテクニック。それは途中でコードに大きな影響を与えるでしょう(多くのコードをヘッダーとインラインファイルに移動する必要があります)。 – nyarlathotep108

+0

はい、私はそれが宗教的にそれに従わないが、テスト駆動設計の多くの側面が非常に好きです。しかし、実装を書く前に起こる可能性のある小さなシナリオごとに単体テストを作成しなくても(TDDが教えてくれるように)、あなたはまだ後で考えてテストを追加することができますいくつかの深刻なコードの再設計 - あなたはそれから離れません、テストは邪魔です。個人的には私が書くすべてのものをテンプレート化したいので、Mockテンプレートパラメータを適用することができます – Smeeheey

関連する問題