Junit備忘録【サービス・ロジック層】

現場で何回も調べてしまうので備忘録して内容をまとめる


####Mock　返り値にdummyの変数をセット
```java
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

	@Autowired
	DemoService demoService;

	@Mock
	DemoLogic demoLogic;

	@Test
	void demoTest() {
		when(demoLogic.DemoLongLogic()).thenReturn(1L);

		// 引数ある場合はany()で
		when(demoLogic.DemoLongLogic(any())).thenReturn(1L);
	}
```

####Mock　返り値なし　voidの場合
```java
        doNothing().when(demoLogic).DemoVoidLogic();
```

####Mock　返り値が配列
```java
        Users users1 = new Users();
        Users users2 = new Users();
        //配列が一つの場合
        when(demoLogic.DemoListLogic(any())).thenReturn(Collections.singletonList(users1));
        //配列が複数の場合
        when(demoLogic.DemoListLogic(any())).thenReturn(Arrays.asList(users1, users2));
```

####Mock　CompletableFuture　非同期処理メソッド
基本的には他のMockと変わらないが返却値に`CompletableFuture.completedFuture`が必要

```java
        when(demoLogic.DemoLongLogicAsync()).thenReturn(CompletableFuture.completedFuture(1L));        
```

####Mock　強制的にException エラー発生させる

```java
        when(demoLogic.DemoLongLogic()).thenThrow(new RuntimeException());          
```

####Mock　強制的にException エラー発生させる　戻り値がVoid

```java
        doThrow(new RuntimeException()).when(demoLogic).DemoVoidLogic();       
```

####強制的にException エラーメッセージの確認
ターゲットメソッドで使用

```java
        Exception exception = assertThrows(Exception.class, () -> demoService.DemoLongService());
        assertEquals("エラーが発生しました", exception.getMessage());          
```

####テスト中対象のメソッドが何回呼ばれたか監視する
```java
        verify(demoLogic, times(1)).DemoVoidLogic();
```

####Loggerの確認
```java
        @Captor
        ArgumentCaptor<String> messageCaptor;
        @Captor
        ArgumentCaptor<Exception> exceptionCaptor;
        @Mock
        Logger logger;

//省略

        verify(logger, times(1)).error(messageCaptor.capture(), execptionCaptor.capture());
        assertThat(messageCaptor.getValue()).isEqualTo("DEMO");
        assertThat(execptionCaptor.getValue()).isNotNull();
```

####Loggerの確認(＠Slf4j)
```java
import ch.qos.logback.classic.Logger;

        @Captor
        private ArgumentCaptor<LoggingEvent> captorLoggingEvent;

        @Mock
        private Appender mockAppender;

//省略

        Logger logger = (Logger) LoggerFactory.getLogger(DEMO.class);
        logger.addAppender(mockAppender);

        verify(mockAppender, times(1)).doAppend(captorLoggingEvent.capture());
        // ログレベルの確認
        assertEquals("INFO", captorLoggingEvent.getValue().getLevel().toString());
        // メッセージの確認
        assertEquals("demo_message", captorLoggingEvent.getAllValues().get(0).getMessage());
```


#### any()についての注意 NullpointerException　~~~argument matchers: any()
なんでもかんでもany()にすれば良いというわけではなく
引数がLongなら`anyLong()`　Stringなら`anyString()`と設定する必要がある

```java
	when(demoLogic.DemoLongLogic(any())).thenReturn(1L); //ではなく
	when(demoLogic.DemoLongLogic(anyLong())).thenReturn(1L);
```

#### @MockBeanの使いどころ
基本的には@Mockで問題ない
インタフェースでBeanなどを読み込んでいる部分などには@MockBeanでモック化が可能になる
またメソッド内で別のメソッドを呼び出しそこにあるメソッドをモック化したい場合は使用する
@MockBeanを使いすぎると重くなのでなるべく量は減らすように


```java
	public class DemoBean implements InitializingBean {
        // 省略
        }
```

まだまだ量が多くなりそうなのでここまで。。。（更新予定）
次回は
・Daoのテスト
・APIのテストJsonでスタブをひっかけるテストを書いていこうかな