Mockitoの使い方 色々

# はじめに

本記事ではMockitoの基本的な使い方について（半分自分用のメモ的に）色々と記載していきます。

## Mockitoとは

Mockitoとはなんぞや？という方のために、軽く説明を記載しておきます。  
MockitoとはJavaの単体テスト（JUnitなど）のために開発されたモックフレームワークです。  
テストでモックオブジェクトを直感的に操作できることを目的として開発されており、  
記述されたテストコードの可読性が高く、分かりやすい検証エラーを生成することが特徴です。

依存する部品（クラス）から任意の戻り値をテスト対象クラスに返すのが困難な場合などに、  
部品をモック化することでテスト対象クラスに焦点を当てたテストを行うことが可能となります。

# ライブラリ追加

org.mockitoのライブラリをプロジェクトに追加し、依存関係を設定しておく必要があります。  
例えば、Mavenの場合は以下の設定をpom.xmlのdependenciesに追加します。

```pom.xml
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>任意のバージョン</version>
</dependency>
```

# モックオブジェクトの生成

## アノテーションを使用する方法

モック化したいオブジェクトに対して@Mockアノテーションを付与し、  
MockitoAnnotations.initMocksメソッドに自クラス(this)を引数として指定することで、  
オブジェクトをモック化することができます。

```アノテーションを使用する方法.java
@Mock
private SampleComponent1 sampleComponent1;
@Mock
private SampleComponent2 sampleComponent2;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}
```

## 生成用メソッドを使用する方法

mockメソッドにモック化したいオブジェクトのClassオブジェクトを引数として指定することで、  
オブジェクトをモック化することができます。

```生成用メソッドを使用する方法.java
private SampleComponent1 sampleComponent1;
private SampleComponent2 sampleComponent2;

@Before
public void setUp() {
    sampleComponent1 = Mockito.mock(SampleComponent1.class);
    sampleComponent2 = Mockito.mock(SampleComponent2.class);
}
```

# モックオブジェクトを注入する

@InjectMocksアノテーションを使用して、テスト対象クラスにモックオブジェクトを注入することで、  
テスト対象クラス内ではモックオブジェクトを使用してメソッドが動作するようになります。

```モックオブジェクトを注入する.java
// テスト実行クラス
public class SampleTest {
    // モックオブジェクトを注入する
    @InjectMocks
    private Sample sample;
  
    @Mock
    private SampleComponent1 sampleComponent1;
    @Mock
    private SampleComponent2 sampleComponent2;
  
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }
  
    @Test
    public void executeTest() {
        // メソッド内ではモックオブジェクトを使用して動作する
        sample.execute();
    }
}

// テスト対象クラス
public class Sample {
    private SampleComponent1 sampleComponent1;
    private SampleComponent2 sampleComponent2;
  
    public void execute() {
        // モックオブジェクトとなっている
        SampleComponent1.method();
    }
}
```

# モックオブジェクトの振る舞い定義

## publicメソッド 引数あり 戻り値あり

whenメソッド等を駆使してモックオブジェクトのメソッドの振る舞いを定義します。

対象メソッドがpublicメソッド、引数あり、戻り値ありのパターンの場合についてです。

```publicメソッド 引数あり 戻り値あり - 方法1.java
Mockito.when(sampleComponent1.method(想定する引数)).thenReturn(任意の戻り値);
```

```publicメソッド 引数あり 戻り値あり - 方法2.java
Mockito.doReturn(任意の戻り値).when(sampleComponent1).method(想定する引数);
```

- 引数について想定する引数が定まっていない場合に、anyString()、anyInt()、anyObject()などに置き換えることが可能です
   ```publicメソッド 引数あり 戻り値あり - 方法1 - 引数をanyにする.java
   Mockito.when(sampleComponent1.method(anyString())).thenReturn(任意の戻り値);
   ```
- 引数について、引数1は引数が定まっている、引数2は想定する引数が定まっていない場合には、  
  eq(想定する引数) + any〜()を組み合わます  
  ※いずれかの引数にany〜()を使用している場合、それ以外の引数については必ずeq()で囲む必要があります
   ```publicメソッド 引数あり 戻り値あり - 方法1 - 引数をeq + anyにする.java
   Mockito.when(sampleComponent1.method(eq(想定する引数), anyString())).thenReturn(任意の戻り値);
   ```

## publicメソッド 引数なし 戻り値あり

whenメソッド等を駆使してモックオブジェクトのメソッドの振る舞いを定義します。

対象メソッドがpublicメソッド、引数なし、戻り値ありのパターンの場合についてです。

```publicメソッド 引数なし 戻り値あり - 方法1.java
Mockito.when(sampleComponent1.method()).thenReturn(任意の戻り値);
```

```publicメソッド 引数なし 戻り値あり - 方法2.java
Mockito.doReturn(任意の戻り値).when(sampleComponent1).method();
```

## publicメソッド 引数あり 戻り値なし

whenメソッド等を駆使してモックオブジェクトのメソッドの振る舞いを定義します。

対象メソッドがpublicメソッド、引数あり、戻り値なしのパターンの場合についてです。

```publicメソッド 引数あり 戻り値なし.java
Mockito.doNothing().when(sampleComponent1).method(想定する引数);
```

# モックオブジェクトの振る舞い検証

## 呼び出し回数検証

verifyメソッド等を駆使してモックオブジェクトのメソッドが呼び出された回数を検証します。  
当然ではありますが、モックオブジェクトのメソッドが呼び出された後に当処理を入れる必要があります。

```呼び出し回数検証.java
Mockito.verify(sampleComponent1, times(想定回数)).method(想定する引数);
```

# 参考リンク

- [Mockito公式サイト](https://site.mockito.org/)