2

一部の C/C++ プロジェクトで CppUTest の使用を開始しています。特にモッキング拡張機能は良さそうですが、どうやってモックを設定すればいいのか、今悩んでいます。ネットワーク ソケット通信を抽象化するための低レベル クラスを想定します。

私の最初の方法:

size_t CMockSocket::recv(void* buf, size_t len)
{
  return (size_t) mock().actualCall("recv")
      .withParameter("len", (int) len)
      .returnValue().getIntValue();
}

期待値の設定:

mock().expectOneCall("recv")
    .withParameter("len", 20)
    .andReturnValue(15);

ここまでは順調ですね。しかし、私が必要とするのは、より多くのデータを提供することです。この場合、buf ポインターを介して返したい 15 バイトです。.setData()setDataObject()メソッドを使用しようとしました。しかし、関数は、予想される関数呼び出しではなく、名前付き変数にデータを格納しているようです。したがって、後続の呼び出しは前のデータを上書きしますよね?

私の現在の問題は、追加の戻りデータをモッキングメソッドに渡すにはどうすればよいですか? これに対する私の最初のアプローチは、戻り値 (size_t) とデータ バッファーの両方を含む結果のクラスを作成することでした。このような:

クラス CRecvResults
{
公衆:
  size_t m_returnValue;
  ボイド* m_buffer;
  CRecvResults(size_t returnValue, void* バッファ) :
    m_returnValue(戻り値)、m_buffer(バッファ) {}
  〜CRecvResults() {}
};

size_t CMockSocket::recv(void* buf, size_t len)
{
  CRecvResults* pResults =
      (CRecvResults*) モック().actualCall("recv")
      .withParameter("len", (int) len)
      .returnValue().getPointerValue());

  assert (pResults != NULL);
  assert(buf != NULL);
  assert(len >= pResults->m_buffer.length());
  memcpy(buf, pResults->m_buffer.data(), pResults->m_buffer.length());
  pResults->m_returnValue を返します。
}

そして期待:

char* buffer = "少なくとも 15 文字の長さのバッファ コンテンツを返します";
CRecvResults 結果 (15、バッファー);
mock().expectOneCall("recv")
      .withParameter("len", 20)
      .andReturnValue(&results);

質問:これは正しい方法ですか、それとも何か見逃していますか?結果インタープリターをテストする必要があるため、バッファーの内容が必要です。

私の2番目の方法:

bool CMockSocket::send(const void* buf, size_t len)
{
  return mock().actualCall("send")
      .withParameter("len", (int) len)
      .returnValue().getIntValue();
}

期待値の設定:

mock().expectOneCall("送信")
    .withParameter("len", 20)
    .andReturnValue(真);

この場合、テスト対象のコードによって生成された buf の発信データを検証したいと考えています。したがって、そのバッファーの内容 (および長さ) をテスト関数に返す必要があります。このような:

クラスCSendResults
{
公衆:
  bool m_returnValue;
  char* m_buffer;
  size_t m_length;
  CSendResults(bool returnValue, char* buffer, size_t length) :
    m_returnValue(戻り値)、m_buffer(バッファ)、m_length(長さ) {}
  ~CSendResults() {}
};

bool CMockSocket::send(const void* buf, size_t len)
{
  CSendResults* pResults =
      (CSendResults*) モック().actualCall("送信")
      .returnValue().getPointerValue();

  assert (pResults != NULL);
  assert(buf != NULL);
  assert (pResults->m_length >= len);
  memcpy(pResults->m_buffer, buf, len);
  pResults->m_length = len;
  pResults->m_returnValue を返します。
}

そして期待:

文字バッファ[1024];
CSendResults 結果 (真、バッファー、sizeof (バッファー);
mock().expectOneCall("送信")
      .withParameter("len", 20)
      .andReturnValue(&results);

// 結果の内容をさらにチェックします...

これは非常に見苦しく、私には多くのオーバーヘッドがあります。再び私の質問:これは正しい方法ですか、それとも何か見逃していますか?

そして私の最後の質問: 完全に間違った方法でテストしている可能性はありますか? 経験談や実践を教えてください!

4

2 に答える 2

0

次の醜い回避策を使用しています。戻り値の構造体型と、偽の関数で必要な追加データを定義します。私は、expectOneCall() を呼び出す 1 つのインスタンスを割り当てて埋め、".andReturnValue()" を使用して渡します。偽の関数では、"...returnValue().getPointerValue()" でデータを取得し、戻り値を struct->rc に設定し、追加のデータを処理します (コピーしてバッファーに比較します)。偽の関数を終了する前に、構造が解放されます。

このようにして、必要な追加データが関数呼び出しのパラメーター リストにバインドされます。

フォルトス

于 2013-07-13T00:50:52.107 に答える