JUnit + Mockito + PowerMock チートシート

# 目次

* [使用環境](#使用環境)
* [モック-スパイオブジェクトの生成](#モック-スパイオブジェクトの生成)
* [メソッドのスタブ化](#メソッドのスタブ化)
* [protected-private変数の設定-取得](#protected-private変数の設定-取得)
* [メソッドの実行](#メソッドの実行)
* [メソッドの実行回数の検証](#メソッドの実行回数の検証)
* [その他](#その他)
* [参考文献](#参考文献)

# 使用環境

| フレームワーク | バージョン |
|:-:|:-:|
| JUnit  |  4.12 |
| Mockito  |  2.7.22 |
| PowerMock  |  1.7.4 |

# モック-スパイオブジェクトの生成

### モックオブジェクト

```java
@Mock
Sample SampleMock;
```

### スパイオブジェクト

```java
@Spy
Sample SampleSpy = new Sample();
```

### モックオブジェクト(PowerMockito)

```java
Sample SamplePowerMockitoMock = PowerMockito.mock(Sample.class);
```

### スパイオブジェクト(PowerMockito)

```java
Sample SamplePowerMockitoSpy = PowerMockito.spy(new Sample());
```

# メソッドのスタブ化

### publicメソッド

```java
doReturn(2020).when(SampleMock).getYear();
```

### privateメソッド

```java
PowerMockito.doReturn(2020).when(SampleMock, "getYear");
```
### インスタンス生成のスタブ

```java
PowerMockito.whenNew(Sample.class).withAnyArguments().thenReturn(SampleMock);
```
### staticメソッド

※PrepareForTest に Sample.class を追加のこと

```java
PowerMockito.mockStatic(Sample.class);
when(Sample.getYear()).thenReturn(2020);
```

# protected-private変数の設定-取得

### 非static変数の設定

```java
Whitebox.setInternalState(SampleInstance, "year", 2020);
```

### 非static変数の取得

```java
int actualYear = Whitebox.getInternalState(SampleInstance, "year");
```

### static変数の設定

```java
Field field = Sample.class.getDeclaredField("year");
field.setAccessible(true);
field.set(null, 2020);
```

### static変数の取得

```java
Field field = Sample.class.getDeclaredField("year");
field.setAccessible(true);
int actualYear = (int)field.get(null);
```

# メソッドの実行

### protected, privateメソッド

```java
Whitebox.invokeMethod(SampleInstance, "getYear");
```

# メソッドの実行回数の検証

### publicメソッド

```java
verify(SampleMock, times(1)).getYear();
```

#### 引数の型が合っていればよい場合

```java
verify(SampleMock, times(1)).getYear(ArgumentMatchers.any(String.class));
```

### protected, privateメソッド

```java
PowerMockito.verifyPrivate(SampleMock, times(1)).invoke("getYear");
```

### staticメソッド

```java
PowerMockito.verifyStatic(Sample.class);
Sample.getYear();
```

# その他

### suppress

※ PrepareForTest に Sample.class を追加のこと

```java
PowerMockito.suppress(PowerMockito.method(Sample.class, "getYear"));
```

### replace

※ PrepareForTest に Sample.class を追加のこと

```java
Method method = SampleInstance.getClass().getMethod("getYear");
PowerMockito.replace(method).with(
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return 2020;
         }
    }
);
```

### ArgumentCaptor

```java:source.java
hogehoge.setSample(new Sample(){
    @override
    public int getYear(){
        return 2020;
    }
})
```
※ hogehoge に hogehogeMock を代入のこと

```java:test.java
ArgumentCaptor<Sample> SampleCaptor = ArgumentCaptor.forClass(Sample.class);
verify(hogehogeMock, times(1)).setSample(SampleCaptor.capture());
Sample SampleObj = SampleCaptor.getValue();
```

# 参考文献

* [PowerMock - Github](https://github.com/powermock/powermock)
* [【Java】リフレクションでprivateな変数を参照・設定する](https://qiita.com/11295/items/773e7395889e05f605ae)
* [PowerMockでsuperメソッド呼び出しをモックする方法](https://qiita.com/junn8k/items/9a2cc8ade20b73d6239a)
* [mockitoでArgumentCaptorを使い、引数を検証する](https://qiita.com/kyabetsuda/items/16c565460580a8354f6a)