0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Visual StudioのGoogle Testプロジェクトの使い方 その2 ~Google Mockの追加~

Posted at

はじめに

前回

そもそもMockって?

クラスが呼び出すクラスなりライブラリなりの代用。
テストで下位から返されるもので処理が変わったりする場合に、呼び出すモジュールの処理結果がテストで必要な結果になるよう、あれこれ操作するのは大変なので、好きな結果を返すモジュールに差し替えて動かすのがMockです。

Google Mockのセットアップ

セットアップといってもNuGetで持ってくるだけ。
「ツール -> NuGetパッケージマネージャー -> ソリューションのNuGetパッケージの管理」を選択して、管理画面を開きます。
参照タブを選択して、googlemockで検索して「googlemock.v140.windesktop.static.rt-dyn」を探します。
GoogleMockのパッケージ.jpg
「googlemock.v140.windesktop.static.rt-dyn」を選択して、右側に表示されるインストールするプロジェクトの選択で、TargetProjectTestにチェックを入れてインストールします。
バージョンは最新で問題ないはずです。(現在の最新1.7.0.1)
(ちなみにgooglemockとだけ名前がついているものがありますが、ソースファイルだけ突っ込まれていて、ビルドの構成をするようなファイルは一切ないので、普通にGithubからGoogleMockのソースを持ってきて自分でビルドして使うほうが100倍マシです。)

で、バージョンは問題ないのです。
問題はNuGetのパッケージ自体に間違いがあることです。

GoogleMockのフォルダ修正

Google Mockのヘッダーファイルはgmockフォルダ下のヘッダーファイルを参照するようになっていますが、パッケージの中のフォルダはgtestになっているので、このまま使うとどう足掻いてもエラーになります。
ということで、先程ソリューションファイルがあるフォルダの直下のpackagesフォルダ内にインストールされた、GoogleMockのパッケージ内のフォルダ名を修正します。

packagesフォルダにある「googlemock.v140.windesktop.static.rt-dyn.X.X.X.X」(X.X.X.Xはインストールしたバージョン)下の「build\native\include」にある「gtest」フォルダの名前を「gmock」に変更します。

リンクの追加

package下のgmock.libをリンクする必要があるので、「構成プロパティ -> リンカー -> 入力 -> 追加の依存ファイル」にgmock.libを追加します。
以下を追加すれば、ビルド環境毎同じ設定でビルドできます。
「$(SolutionDir)packages\googlemock.v140.windesktop.static.rt-dyn.1.7.0.1\build\native\lib\$(Platform)\v140\$(Configuration)\gmock.lib」

ここまでの設定でGoogle Mockを使用できるようになります。
このままビルドしてもGoogle Mockを使っていないので、設定ができているか分からないので、簡単なテストを追加していきます。

Google Mockを使ったテストの追加

Linux環境での情報が多いですが、Google Mockの使い方自体はWindowsでも変わらないので一気にいきます。
Google Mockを使えるよう、前回のソースでテストしたメソッドとは別に、インターフェースクラスを使用する下位のクラスを使うメソッドを実装します。

インターフェースクラスの追加

少々雑ですが、TargetClass.hに追加していきます。

class InterfaceClass
{
public:
	virtual ~InterfaceClass() {};
	virtual int Interface() = 0;
};

インターフェースの実装クラスの追加

インターフェースクラスと同じくTargetClass.hに追加していきます。

class InheritanceClass : public InterfaceClass
{
public:
	int Interface() override
	{
		return 1;
	}
};

下位クラスを呼び出すメソッドの追加

前回作成したTargetClass.hに新しく追加します。

class TargetClass
{
public:
	bool PublicMethod(int input);

	bool PublicMethod2(int input);

	InterfaceClass* imple_;

private:
	FRIEND_TEST(TargetClassTest, PrivateMethodTest);
	bool PrivateMethod(int input);

};

Mockの追加

テストの方に書くと分かりにくくなるので、TargetProjectTestにMockClass.hを追加します。

MockClass.h
#pragma once
#include "TargetClass.h"
#include <gmock/gmock.h>

class MockClass : public InterfaceClass
{
public:
	MOCK_METHOD0(Interface, int(void));
};

テストの追加

Mockを使用したテストを追加します。

using ::testing::AtLeast;

TEST(TargetClassTest, MockTest) {
	TargetClass target;

	MockClass *mock = new MockClass();
	EXPECT_CALL(*mock, Interface()).Times(AtLeast(3));

	target.imple_ = mock;

	EXPECT_EQ(false, target.PublicMethod2(2));

	delete target.imple_;
}

テスト追加後の各ファイル

TargetClass.h
#pragma once
#include "gtest/gtest_prod.h"
#include <memory>

class InterfaceClass
{
public:
	virtual ~InterfaceClass() {};
	virtual int Interface() = 0;
};


class InheritanceClass : public InterfaceClass
{
public:
	int Interface() override
	{
		return 1;
	}
};

class TargetClass
{
public:
	bool PublicMethod(int input);

	bool PublicMethod2(int input);

	InterfaceClass* imple_;

private:
	FRIEND_TEST(TargetClassTest, PrivateMethodTest);
	bool PrivateMethod(int input);

};
TargetClass.cpp
#include "TargetClass.h"

bool TargetClass::PublicMethod(int input)
{
	if (input >= 0)
	{
		return true;
	}

	return false;
}

bool TargetClass::PublicMethod2(int input)
{
	if (input > imple_->Interface())
	{
		return true;
	}

	return false;
}

bool TargetClass::PrivateMethod(int input)
{
	if (input <= 0)
	{
		return true;
	}

	return false;
}
TargetProject.cpp
#include <iostream>
#include "TargetClass.h"

int main()
{
    TargetClass target;

    std::cout << target.PublicMethod(1) << std::endl;

    return 0;
}
MockClass.h
#pragma once
#include "TargetClass.h"
#include <gmock/gmock.h>

class MockClass : public InterfaceClass
{
public:
	MOCK_METHOD0(Interface, int(void));
};
test.cpp
#include "pch.h"
#include "gmock/gmock.h"
#include "TargetClass.h"
#include "MockClass.h"

using ::testing::AtLeast;

TEST(TargetClassTest, PublicMethodTest) {
	TargetClass target;

	EXPECT_EQ(true, target.PublicMethod(1));
	EXPECT_EQ(false, target.PublicMethod(-1));
}

TEST(TargetClassTest, PrivateMethodTest) {
	TargetClass target;

	EXPECT_EQ(false, target.PrivateMethod(1));
	EXPECT_EQ(true, target.PrivateMethod(-1));
}

TEST(TargetClassTest, ImplTest) {
	TargetClass target;

	target.imple_ = new InheritanceClass();

	EXPECT_EQ(false, target.PublicMethod2(2));

	delete target.imple_;
}

TEST(TargetClassTest, MockTest) {
	TargetClass target;

	MockClass *mock = new MockClass();
	EXPECT_CALL(*mock, Interface()).Times(AtLeast(3));

	target.imple_ = mock;

	EXPECT_EQ(false, target.PublicMethod2(2));

	delete target.imple_;
}

int main(int argc, char** argv) {
	::testing::InitGoogleMock(&argc, argv);
	return RUN_ALL_TESTS();
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?