gmockについて勉強してみた(6):ダブルポインタ引数を持つメソッドのモック

どもです。

前回の投稿までの中で、ポインタ引数、特にシングルポインタ引数を持つメソッドのモックを定義する内容を書いてきました。
今回は、ポインタ引数、特にダブルポインタ引数を持つメソッドのモックをgmockで定義してみます。

0. 作業環境:

作業環境です。
これまでと同様に、以下の環境で作業を行っています。

項目 内容
CPU Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz 3.20 GHz
RAM 16.0 GB (15.9 GB 使用可能)
OS Windows 10 Professional 22H2 (19045.5487)
IDE Visual Studio Community 2022 (64bit), Version 17.14.8
CMake version 4.1.0

1. サンプルメソッド

私個人の経験ですが、ダブルポインタ引数は出力となります。
そのため、出力となるダブルポインタ引数を持つメソッドを呼び出すメソッドを考えます。

1.1. テストダブルを使用するメソッド

今回は、以下のような配列のアドレスをポインタに格納して返すメソッドを例に、話を進めます。


// テスト対象クラス
class BufferUser {
public:
	BufferUser(IAllocator& alloc) : alloc_(alloc) {}
	int UseBuffer()
	{
		int* buffer = nullptr;
		alloc_.AllocateBuffer(&buffer);
		if (!buffer) return -1;
		int sum = 0;
		for (int i = 0; i < 3; ++i) {
			sum += buffer[i];
		}
		return sum;
	}
private:
	IAllocator& alloc_;
};

UseBufferメソッドは、内部で呼び出しているAllocateBuffer()メソッドが返したアドレスの実体(配列)に格納された値の和を返します。

1.2. テストダブル

テストダブル化するAllocateBuffer()メソッドは、以下のようなI/Fを持ちます。


void AllocateBuffer(int** out_ptr)

インターフェースも含めれば、以下のようになります。


// インターフェース
class IAllocator {
public:
	virtual ~IAllocator() = default;
	virtual void AllocateBuffer(int** out_ptr) = 0;
};

このメソッドのテストダブルは、gmockを用いて以下のように定義/実装できます。


// モック
class MockAllocator : public IAllocator {
public:
	MOCK_METHOD(void, AllocateBuffer, (int** out_ptr), (override));
};

2. テストドライバ

前出のテストダブルがテスト実行時に呼び出された際の動作を、テストダブルで指定します。
指定したい動作は、予め指定された配列のアドレスを、引数のダブルポインタの実体に格納する、という動作です。
この動作は、gmockのSetArgPointeeメソッドで指定します。
具体的なコードは、以下のようになります。


SetArgPointee<0>(test_data)

ここでtest_dataは、以下のように予め宣言しておきます。


static int test_data[3] = { 1, 2, 3 };

これらのことを踏まえたテストドライバ全体の実装は、以下のようになります。


// テスト
TEST(BufferUserTest, DoublePointerArgument)
{
	MockAllocator mock;

	// モックが返す配列データ
	static int test_data[3] = { 1, 2, 3 };

	// out_ptr(int**)の指す先に test_data のアドレスをセット
	EXPECT_CALL(mock, AllocateBuffer(_))
		.WillOnce(DoAll(
			SetArgPointee<0>(test_data)  // 0番目の引数(int** out_ptr)に test_data のアドレスを代入
		));

	BufferUser user(mock);
	EXPECT_EQ(user.UseBuffer(), 6); // 1+2+3=6
}

3. 使用しているメソッド

前出のテストドライバ内で使用されているgmockのメソッドの仕様を確認します。
このメソッドは、以前の投稿の中ですでに登場しております。
しかし、その投稿の中では、動作については書きましたが、説明をしていませんでした(ゴメンナサイ)。
なので、ここで改めて説明をします。

SetArgPointeeは、gmockの公式サイトでは、以下のように説明されています。

SetArgPointee<N>(value) N-番目(0基準)の argument によって指される変数に、value を代入します。

この説明は…特段解りにくいということはないので、言い換えは省略します。

4. 結論

今回は、ダブルポインタ引数を持つテストダブルをgmockで定義、実装、動作を指定してみました。
ポインタ引数について、入出力の方向が「出力」であれば、シングルポインタ、ダブルポインタともに「SetArgPointee」メソッドを使用することで、出力する値を指定することができます。

このようにgmockにより、出力となるダブルポインタ引数を持つメソッドのテストダブルを、簡単かつ効率的に定義、実装することができることが分かりました。

この記事の内容が、誰かの助けになれば幸いです。
ではっ!