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

# はじめに
[前回](https://qiita.com/aki_senri/items/3b764bc15475c949fc7c)

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

# Google Mockのセットアップ
セットアップといってもNuGetで持ってくるだけ。  
「ツール -> NuGetパッケージマネージャー -> ソリューションのNuGetパッケージの管理」を選択して、管理画面を開きます。  
参照タブを選択して、googlemockで検索して「googlemock.v140.windesktop.static.rt-dyn」を探します。  
![GoogleMockのパッケージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654263/8233aa10-fa2f-5479-ad48-03cf8e22bac4.jpeg)
「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を追加します。
```ruby: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_;
}
```

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

```ruby: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);

};
```
  
```ruby: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;
}
```
  
```ruby:TargetProject.cpp
#include <iostream>
#include "TargetClass.h"

int main()
{
    TargetClass target;

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

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

class MockClass : public InterfaceClass
{
public:
	MOCK_METHOD0(Interface, int(void));
};
```
  
```ruby: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();
}
```