2017-09-26 1 views
2

私は引数 "struct with pointers"をとる関数を含むCライブラリ(..hhh)を嘲笑しています。私の目標は、これらのポインターが指しているデータについていくつかの期待をすることです。ライブラリ関数は即座に引数を消費します。すなわち、これらの構造体は、関数が呼び出された後に範囲外になる可能性がある。コード内引数を直接消費する必要がある関数を嘲笑するより良いアプローチ

struct A 
{ 
    B* somePointer; 
} 

class ClassUnderTest 
{ 
public: 
    ClassUnderTest() 
    { 
     B arbitraryStruct; 
     A structArg; 
     structArg.somePointer = &arbitraryStruct; 
     C_LibraryFunction(&A); 
    } 
}; 

私の解決策は、GTEST 'アクション' を定義することで、引数を保存することです。この動作では、arbritraryStructをいくつかのグローバルに保存し、私の期待の魔法を実行します。例えば

B arbitraryStruct; 
ACTION(captureB) 
{ 
    const A* a= arg0; 
    arbitraryStruct = *a->somePointer; 
} 

Test(TestClassUnderTest, testIt) 
{ 
    EXPECT_CALL(clibrary, 
    C_libraryFunction(testing::_)).WillOnce(DoAll(captureB()); 
    ClassUnderTest classUnderTest; 

    EXPECT_EQ(bla, B.arbitraryStruct); 
} 

これは機能しますが、少し包括的です。私が嘲笑する必要があるlibの呼び出しがあり、複雑な構造を含むものもあります。怠惰なプログラマーとして、これはより良い方法でこれができるように感じます。誰かがより良いアプローチを考え出すことができますか?

ありがとうございます!

答えて

1

良い方法はではなく、です。代わりに、それらの関数を使用してクラスを作成し、代わりにそのクラスをモックする必要があります。バグの可能性を避けるため、このクラスはできるだけシンプルにする必要があります。例えば

struct MyIface { 
    virtual ~MyIface(){} 

    virtual void Clog() = 0; 
}; 

struct VeebleFitzer { 
    VeebleFitzer() : a(funcA()) { 
    } 
    virtual void Clog() { 
    funcX(a); 
    funcY(); 
    } 

    int a; 
}; 

その後、彼らが必要としているどこにオブジェクトを渡すために、依存性注入のいくつかの種類を使用します。


あなたはいつもあなたのコードをテストするために(「リアル」、およびないあざけり、関数を含む)実際のリソースを使用する機能テストを作成することができます。

+0

フィードバックに感謝します!あなたの完全な権利、その方法は、外部コンポーネントを抽象化するためのインターフェイスを定義するためにクリーナー(私の場合は、vulkan API)。今私はそれを考える、私がしようとしているのは実際にテストの下にも "変換層"を置くことです。このパスを続けるのは良い考えではないかもしれません...ここでの課題は、一部のパーツでのパフォーマンスが本当に重要であり、私がこの分野でシンプルに保つことができないかどうかはわかりませんが、それは別のディスカッションです –

+0

@SvenRademakersそれはあなたが望むものする。機能テストは、あなたが望むことを行う必要があります - 実際の関数を使ってgtestでテストを書く(それらをモックしないでください)。上記の機能をテストしたい場合は、ユニットテストと模擬機能を以下に示します。 –

関連する問題