0

A次のクラスとがあるとしましょうB:

class A
{
    virtual void Init() { DoSomething(); }
};

class B : public A
{
    virtual void Init() { DoSomethingSpecial(); A::Init(); }
};

単体テストでは、 のみをテストします。つまり、呼び出すと実際に が呼び出されることをHippomocksBを使用してテストします。B::Init()DoSomethingSpecial()

B* b_p = new B();
m_mockRepository_p->ExpectCall(b_p, DoSomethingSpecial);
b_p->Init();

Aからのすべての呼び出しを期待したくないので、次のInit()ように記述します。

m_mockRepository_p->ExpectCall(b_p, A::Init);

最後の期待値は未処理の例外を引き起こしますが、呼び出しているメソッドと期待したい基本バージョンを混在させているので問題ないと思います。b_pへのキャストAは役に立ちません。

その特定のユースケースに対する解決策はありますか?

4

1 に答える 1

0

... これは興味深いものです。これには解決策がないと思います。A::Init への呼び出しは、仮想関数テーブルを介して行われるわけではないため (どちらを呼び出すかが明示的にわかっているため)、モックできない非仮想関数に分類されます。

これを追加するための複雑な要因は、B で A::Init のアドレスを取得した場合でも vtable ポインターを取得するため、必要に応じて関数を置き換えることさえできないことです (たとえば、C 関数のモックを使用して論理)。

これを解決するには、一般的なリファクタリング ソリューションをお勧めします。A と B を独立したクラスにするか、B に A を含めるか (プライベート継承)、A と B からインターフェイスを抽出して B をデコレータにします。最後のほうがいいように聞こえますが、A と B が実際に何であるかによって異なります...

于 2014-01-19T22:25:16.390 に答える