Mockitoが難しいのでUdemyで勉強しました



# 概要
現在SpringBootのテストコードの勉強中です。
私の実力不足によりテストコードはとても難しく試行錯誤している状態です。

mockitoを使うのですが
mockitoについて公式ドキュメントを読んでも全く理解できませんでした…

この現状を打開すべく、Udemyで講座を受けました。

私は現状なんとなくしか理解してないです。大まかな感じが伝われば幸いです。
正確な情報は公式Documentと講座の方で確認お願い致します。


# 受けた講座について

**Testing Spring Boot: Beginner to Guru**

https://www.udemy.com/course/testing-spring-boot-beginner-to-guru

講師名:John Thompson氏
Section9:Getting Started with Mockito

音声、字幕共に英語です。理解に時間は掛かりますが情報量が多く満足しています。


SpringBootのテスト手法を幅広く扱っています。総再生時間は１７時間です。
junit5を触ったことがあるという方は必要なセクションから始めれば問題ないと私は考えます。


# 環境
IDE：InteliJのCommunity

githubのURL

https://github.com/springframeworkguru/testing-junit5-mockito/tree/annotation-mocks

# 習得した内容


## テストする対象
JPAを使ってます。ServiceとRepositoryとSpringDataJPAのテストを行っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/62bfd6c7-6278-ce29-fbc6-49687a9f6e72.png)

画像の引用元「https://terasolunaorg.github.io/guideline/5.5.1.RELEASE/ja/ArchitectureInDetail/DataAccessDetail/DataAccessJpa.html」

service/springdatajpa

``` SpeacialtyService.java
public interface SpecialtyService extends CrudService<Speciality, Long> {
}

```

service/map
``` SpecialityMapService.java
public class SpecialityMapService extends AbstractMapService<Speciality, Long> implements SpecialtyService {
    @Override
    public void deleteById(Long id) {
        super.deleteById(id);
    }
}

```

repositories
``` SpecialtyRepository.java
public interface SpecialtyRepository extends CrudRepository<Speciality, Long> {
}
```

service/springdatajpa
```SpecialitySDJpaServiceTest.java
public class SpecialitySDJpaService implements SpecialtyService {

    private final SpecialtyRepository specialtyRepository;

    public SpecialitySDJpaService(SpecialtyRepository specialtyRepository) {
        this.specialtyRepository = specialtyRepository;
    }

    @Override
    public void deleteById(Long aLong) {
        specialtyRepository.deleteById(aLong);
    }
}



```







## ＠Mock と ＠injectMock
branchは　inject-mock
``` SpecialitySDJpaServiceTest.java
@ExtendWith(MockitoExtension.class)
class SpecialitySDJpaServiceTest {

    @Mock
    SpecialtyRepository specialtyRepository;

    @InjectMocks
    SpecialitySDJpaService service;

    @Test
    void deleteById() {
        service.deleteById(1l);
    }

    @Test
    void testDelete() {
        service.delete(new Speciality());
    }
}


```
SpecialitySDJpaServiceにブレークポイントを打ってデバッグを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f81791c2-71f8-3148-3b7d-cf2265b0937e.png)

デバッグ実行後serviceの中にrepositoryの値が入っていることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c0010ae9-4c59-fed8-dda3-d76e709b7df6.png)



## verify
branchは「verify」
verifyを使ってインスタンスの呼び出し回数のテストを行います。
色々種類ありますが、timeについて紹介します。
timeは指定したインスタンスの呼び出し回数についてテストをします。

```SpecialitySDJpaServiceTest.java
@ExtendWith(MockitoExtension.class)
class SpecialitySDJpaServiceTest {

    @Mock
    SpecialtyRepository specialtyRepository;

    @InjectMocks
    SpecialitySDJpaService service;

    @Test
    void deleteById() {
        service.deleteById(1l);
        service.deleteById(1l);

        verify(specialtyRepository, times(1)).deleteById(1l);
    }

}


```
time(1)の値をtime(2)などにして変更し実行するとエラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/3041aa3b-eacf-5102-eafc-ee0a24e2d401.png)


## when
branchは「return-val-form-mock」

```SpecialitySDJpaServiceTest.java
@ExtendWith(MockitoExtension.class)
class SpecialitySDJpaServiceTest {

    @Mock
    SpecialtyRepository specialtyRepository;

    @InjectMocks
    SpecialitySDJpaService service;

    @Test
    void findByIdTest() {
        Speciality speciality = new Speciality();
        Speciality tmp = new Speciality();

        when(specialtyRepository.findById(1L)).thenReturn(Optional.of(speciality));


        System.out.println(when(specialtyRepository.findById(1L)).thenReturn(Optional.of(speciality)));

        Speciality foundSpecialty = service.findById(1L);

        assertThat(foundSpecialty).isNotNull();
        System.out.println(specialtyRepository.findById(1L));
        System.out.println(specialtyRepository.findById(2L));  //入ってない

    }

}

```
デバッグ結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/6cac18c9-1484-22a7-06b4-3203151783f7.png)

Spcialityクラスが紐付けられていることが確認できます。

ターミナル画面の出力結果確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/98c01fad-7601-d4ed-5ca3-932ba39332c7.png)

1Lは値が入ってますが、
2Lの方は値が入っていません。
引数を指定する役割があると思われます。


# まとめ
デバッグの仕方とか勉強になりました。
whenは今まで使っていませんでした勉強になります。

次に取り組むこと
Section10:Behavior Driven Mockito

https://qiita.com/RYA234/items/f6274bd5ee44cf5871c3#%E7%BF%92%E5%BE%97%E5%86%85%E5%AE%B9