JUNITテスト作っといてと言われたら…

## この記事の対象者
* 環境がPJ側ですでに用意されている
* JUnit未経験/JUnit初心者
* JUnitでテストをするってことは分かるけど、どうコーディングすればいいかわからない

### あなたが考えるべき流れ
#### 1. テスト対象のメソッドを理解しよう
　例えばテスト対象のクラスがServiceImplだった場合。
　ServiceImplには、呼ばれるべきpublicな __メインメソッド__ があり、その中で実行される __外部メソッド__ や  __privateメソッド__ があるはず。

　テスト観点は 
　"__メインメソッド__ が __外部メソッド__ の結果に左右されず正常終了し、かつ、想定通りの異常終了をするか"
　である。
　なのでまずは動作を確認すべき __メインメソッド__ がどれであるかを把握しよう。

#### 2. 得たい結果を把握しよう
　JSON、ResultCode、インスタンス...etc
　テスト実行後にどのような結果が返れば終了か、文字列系であればどこかに控えておこう。

#### 3. MOCK（モック）とは何か知ろう
　手順１で述べたように、メインメソッドは外部メソッドの結果に左右されてはならない。
　そこで、
　"外部メソッドが呼ばれたら固定でこの値（結果）を返せ"
　と命令を埋め込むのが __MOCK__ の役割だ。
　詳しい使い方は後述するが、__仮想動作を設定する変数__ と認識しておこう。
　※スタブ化する、とも呼ばれる。

### 全体像を眺める

``` Java
@RunWith(MockitoJUnitRunner.class)
public class TargetClassTest {

  // 下準備開始
  @Mock
  private Mapper mockMapper;

  @InjectMocks
  private TargetTestServiceImpl service;

  @BeforeEach
  public void setup() {
    // パターン１
    MockitoAnnotations.openMocks(this);  
    // パターン２
    ReflectionTestUtils.setField(service, "mapper", mockMapper);
  }
  // 下準備終了

  // 以下テスト記述
  @Test
  @DisplayName("正常終了系")
  public test001() throws Exception {
    // １
    when(mockMapper).exeQuery(any()).thenReturn(anyString());
    // ２
    ResultCode actualResult = service.method();
    // ３
    assertEquals(ResultCode.RETURN_SUCCESS, actualResult);
  }
}

```

### テスト全体の構造
　```test001```メソッドに注目する。
　番号順にざっくり言ってしまうと、１で下準備をし、２でメソッドを実行し、３で結果を比較している。
　それらを順に解説していく。

#### 1. 下準備

```java 
when(mockMapper).exeQuery(any()).thenReturn(anyString());
```
　上記のコードではメソッドチェーンにより３つのメソッドが呼ばれ、

　when(__この変数で__)
　exeQuery(__引数を問わずexeQueryが呼ばれたら__)
　thenReturn(__何らかのStringを返す__)

　という処理が行われている。
　再三の説明になるが、外部のメソッドに結果が左右されてはならないので、exeQueryメソッドは引数も返り値も仮の物を用意すればいい。

　モック変数を利用するには以下の手順が必要だ。

* @Mockで外部メソッドが定義されているクラスで変数を用意する。
* @InjectMocksでテスト対象となるクラス（ここではサービスクラス）変数を用意する。
* ```MockitoAnnotations.openMocks(this)※1```　というおまじないでテスト対象クラスにモックを注入する。

　変数を用意しおまじないを書くだけで良いので非常に簡単だ。
　ちなみに、おまじない自体は```test001()```に記述しても良い。
　だがその場合にはtest002,003...と増えた場合に毎度記述しなければならないので、面倒だし美しくない。
　そこで@BeforeEachが登場する。
　このアノテーションが付与されたメソッドは __TargetClassTestクラス内の@Testが付いたメソッドが実行される前に毎回実行される__ 様になり、全てのテストメソッドに記述しなければならないような共通下準備をまとめておくことが出来る。

 ※1 おまじないのパターンについて
　　テスト対象クラスのDIが@Autowiredの場合にはパターン１。
　　テスト対象クラスのDIがコンストラクタインジェクションの場合にはパターン２。

#### 2. テストメソッドの実行
```java
ResultCode actualResult = service.method();
```
　ここでは非常にシンプルだ。
　メソッドの返り値を受け取れるクラスの変数を用意し、@InjectMocksが付与されたクラスのテストしたいメソッドを実行する。
　終わり。

#### 3. 結果の確認
```java
assertEquals(ResultCode.RETURN_SUCCESS, actualResult);
```
　assertEqualsメソッドは引数１と２を比較し、一致すれば正常終了するようになっている。
　メソッドとしては引数のどちらがexpected（期待値）でどちらがactual（実行結果）であるかは問われない。
　しかし可読性や慣例として、引数１がexpectedであるので、参画しているPJが逆でない限りは従おう。

### テストの実行
　Eclipseであれば作成したクラスを右クリックし、コンテキストからカバレッジまたはテストの項目、JUNITを選んで実行すればJUNITビューに結果が出力される。


## 上記のサンプルから拡張する
* ```any()```メソッド
例えば```any()```メソッドの種類も沢山ある。```any()```はどこにでも入れられる反面、明確に型を提示しなければならないメソッドでは```anyLong()```や```anyString()```としてやる必要がある。
* ```thenReturn()```メソッド
このメソッドは「この返り値を返せ」というものだが、thenThrow(new Exception("test"))という「Exceptionを返せ」というものがある。
ちなみに、下記の様に```doNothing()```を使用すれば「なにもするな」とも記述できる。
```java
doNothing().when(mockMapper).exeQuery(any());
```

* ```assert```
結果の比較も沢山ある。
使用するJunitのバージョンによりassertThatだったりassertEqualsだったりする。
比較せずassertTrueで真が返っているかと比較することも出来る。
また、以下のように「このメソッドは1回しか呼ばれていないはず」とテストするパターンもある事も覚えておこう。
```java
verify(service, times(1)).exeQuery(any());
```

このように、どのような動作をモック（スタブ）したいのか、どのような結果を確認したいのか、テストの目的をあらかじめ把握することで「JUNIT iterator MOCK」などと検索するワードが浮かぶだろう。

### エラーが起きたら
テスト対象クラスの構成や、ラムダ式をMOCKしようとしていたり（ほぼ不可能）、エラーの原因特定は難しい。
確認点としては、
* デバッグで1行ずつ停止し、外部メソッドを使用する変数に「MOCKITO～」などが代入されているか
　→されていなければMOCKの注入が失敗している。@MOCKではなく@SPYが必要だったりする。大人しく先輩らに「MOCKが上手く注入できないのですが……」と聞いてしまうのも手だ。
* 外部メソッドが想定した仮想値を返さない
　→この場合はテスト対象クラスの動作とMOCKが想定した動作がマッチせず、MOCK動作でなく外部メソッドが実際に動作してしまっていることが考えられる。```any()```の指定または、厳密な変数（文字列や数値）をMOCKで指定してみよう。

などが挙げられる。
テスト対象クラスが複雑であるほどMOCKが難しくなるし、あなたがテスト対象クラスの制作者でなければなおさら難しい。
そして何よりも重要なことが __JUNITでテストされることを想定しコーディングしているか__ である。
あまりにも上手くJUNITがコーディング出来ない場合はあなたの責任でない場合も少なくない。
それをあらかじめ心に留めておくことで心の負担は軽くなるだろう。

## 終わりに
　テストの考え方を本記事で理解できれば他の記事を参考にするといい。
　下準備して、実行して、確認する。このように考えると非常にシンプルに作れるので、難しく考えずトライしてみよう。