web-dev-qa-db-ja.com

関数の引数として渡さずにモックオブジェクトを使用する方法[C ++]

私はC++の既存のコードベースに単体テストフレームワークを統合する過程にあります。 CxxTestをゼロに設定しましたが、CxxTestと組み合わせて他のモッキングフレームワーク(googlemockなど)を使用することができます。

CxxTest(モッキング)とgooglemock(悪名高い亀の例)のチュートリアルを読んだ後、モッククラスを定義し(マクロなどを使用)、モッククラスのオブジェクトを宣言して関数に渡す必要があるという一般的な考えがありますあなたはユニットテストです。現在、既存のコードベースには、それを行うことができない多くのことが発生しています。

明確にする疑似例を次に示します。

class CCandidateForTest
{
    public:
    bool foo(int a)
    {
        CAnotherClass obj;
        int b = obj.bar(a+2);
        if (a == b) {
            return true;
        } else {
            return false;
        }
    }
}

(これは過度に単純化されており、例外もあり、プリミティブ型は他のオブジェクトなどである場合もあります。ただし、一般的な考え方はわかります)(また、オブジェクトの作成は必ずしも直接ではなく、ファクトリーを使用する場合もあります)

関数CCandidateForTest::fooのテストを記述したい。このメソッドは内部でCAnotherClassのオブジェクトを作成します。これをモックしてCAnotherClass::barが異なる値を返し、fooの異なるコードパスがユニットテストでトラバースされるようにする必要があります。

簡単に言えば、問題は、テストされている関数が内部でモックする必要のあるクラスのオブジェクトを作成することです。したがって、モックしたオブジェクトのインスタンスを関数に渡すことはできません。

このような場合にモックを使用するにはどうすればよいですか?これを可能にする特定のモックフレームワークはありますか?

7
dotbugfix

ファクトリを使用してCAnotherClassのインスタンスを作成できます。

class CCandidateForTest
{
    public:
    bool foo(int a)
    {
        std::shared_ptr< CAnotherClassInterface > obj = CAnotherClassFactory::Create();
        int b = obj->bar(a+2);
        if (a == b) {
            return true;
        } else {
            return false;
        }
    }
}

CAnotherClassFactoryは次のようになります。

class CAnotherClassFactory
{
public:
    typedef std::shared_ptr< CAnotherClassInterface > (*fn)();
    static std::shared_ptr< CAnotherClassInterface > Create()
    {
        return createFn();
    }

    static fn createFn;
};

あなたのアプローチについてのランダムな考え:

  • それが過度に単純化されている場合は、それをリファクタリングする方法を考える必要があります。
  • cxxunitよりも優れた単体テストフレームワークがあります。 gtestとcute-test.com
3
BЈовић

工場を使用してください。候補クラスにコンストラクターのファクトリーを受け入れさせます。テストのためにファクトリーを模擬します。そのためにモックlibを使用するか、純粋な抽象ファクトリクラスの個別の製品とテストの実装を単純に使用できます。

4

クラスがジョブを実行するためのオブジェクトを内部で作成する場合、そのオブジェクトは「コラボレーター」ではありません。テスト目的では、これは、同じことを実行する多くのインラインコードがある場合とまったく同じ状況です。言い換えれば、テストが想定しなければならない観点から、このオブジェクトは存在しないため、このオブジェクトをモックすることはできません。

(これは、クラスが多すぎることを示している可能性があり、クラスをリファクタリングしてdoesが真のコラボレーターを持つようにするかどうかを検討する際の引数になる可能性がありますが、それは1つの要因にすぎません-そこにありますクラスを変更せず、モックなしで可能な限りその動作をテストする他の良い理由かもしれません。)

3
Kilian Foth