9

これが私の問題です。初期化時にスレッドを作成し、破棄時にそれを閉じるクラスをモックしたいと思います。私のモック クラスが実際にスレッドを作成して閉じる理由はありません。しかし、クラスをモックするために、私はそれを継承しています。モック クラスの新しいインスタンスを作成すると、基本クラスのコンストラクターが呼び出され、スレッドが作成されます。モック オブジェクトが破棄されると、基本クラスのデストラクタが呼び出され、スレッドを閉じようとします。

実際のリソースを扱わずに RAII クラスをモックするにはどうすればよいでしょうか?

4

4 に答える 4

12

代わりに、型を記述するインターフェースを作成し、実際のクラスとモッククラスの両方にそれを継承させます。だからあなたが持っていた場合:

class RAIIClass {
 public:
  RAIIClass(Foo* f);
  ~RAIIClass();
  bool DoOperation();

 private:
  ...
};

次のようなインターフェイスを作成します。

class MockableInterface {
 public:
  MockableInterface(Foo* f);
  virtual ~MockableInterface();
  virtual bool DoOperation() = 0;
};

そしてそこから行きます。

于 2008-10-12T17:34:37.543 に答える
6

まず第一に、クラスがそれらの使用のためにうまく設計されているかもしれないが、テストのために不十分に設計されているかもしれないことは必ずしも不合理なことではありません。すべてをテストするのは簡単ではありません。

おそらく、モックしたいクラスを利用する別の関数またはクラスを使用したいと思うでしょう(そうでなければ、解決策は簡単です)。前者を「ユーザー」、後者を「モック」と呼びましょう。ここにいくつかの可能性があります:

  1. Mockedの抽象バージョンを使用するようにユーザーを変更します(使用する抽象化の種類(継承、コールバック、テンプレートなど)を選択できます)。
  2. テストコード用に別のバージョンのMockedをコンパイルします(たとえば、テストをコンパイルするときにRAIIコードを#defします)。
  3. Mockedにコンストラクターフラグを受け入れさせて、その動作をオフにします。私は個人的にこれを避けるでしょう。
  4. リソースを割り当てるコストを吸収するだけです。
  5. テストをスキップします。

UserまたはMockedを変更できない場合は、最後の2つが唯一の手段になる可能性があります。ユーザーを変更でき、テスト可能になるようにコードを設計することが重要であると思われる場合は、他のどのオプションよりも先に最初のオプションを検討する必要があります。コードを汎用的/柔軟にすることとシンプルに保つことの間にはトレードオフがあることに注意してください。どちらも素晴らしい品質です。

于 2008-10-12T17:35:55.370 に答える
1

単純なイディオムもあなたに合うかもしれません。Threadクラスを作成し、その下に具体的な実装を組み込みます。正しい#definesと#ifdefsを入力すると、単体テストを有効にしたときに実装が変わる可能性があります。つまり、実行しようとしていることに応じて、実際の実装とモックの実装を切り替えることができます。

于 2008-10-13T02:50:01.650 に答える
0

私が使用したテクニックの 1 つは、何らかの形式のデコレータを使用することです。最終的なコードには、スタック上にインスタンスを作成し、同じメソッドを呼び出すメソッドがありますが、基本クラスへのポインターであるメンバー上にあります。その呼び出しが戻ると、メソッドは作成したインスタンスを破棄して戻ります。

テスト時に、スレッドを作成せず、テストしたいメソッドに転送するだけのモックをスワップします。

class Base{
 protected:
  Base* decorated;
 public:
  virtual void method(void)=0;
};
class Final: public Base{
  void method(void) { Thread athread; decorated->method(); } // I expect Final to do something with athread
};
class TestBase: public Base{
  void method(void) { decorated->method(); }
};
于 2008-10-12T21:22:07.707 に答える