1.最初の導入 --- スタブ(stub)の考え方
Unit テストで、テストしたいメゾっどやクラスが他のクラスAに依存している時、クラスをスタッブで替わる。
例
BusinessクラスにServiceクラスのexecute()に依存する時、以下のコードでServiceのスタブを作成する
public class ServiceStub implements Service{
@Override
public int execute(){
return 0;
}
}
2.MockitoでMockingする
導入のスタブ使用する際に、依存するクラスが多い際、作成するスタブが多く、コード量も増え、非効率となる。そこで、JunitのMockitoを使用し、Mockを作成する。
以下になる
import org.mockito.Mockito.mock;
//Serviceのmockを作成する
Service serviceMock = mock(Service.class)
//Mockの実行条件を設定する
when(serviceMock.execute()).thenReturn(0);
//Buissness中のServiceフィードをMockに設定する
business.service = serviceMock;
//これで、businessでexecute()を実行する時に、0を返す。
3.Mockに関するアノテーションを使用する時
@Mock, @InjectMocks
Junitテストに
//@Runwith(MockkitoJunitRunner.class) //Junit4でMock使用する時に必要
@ExtendWith(MockitoExtension.class) //Junit5でMock使用する時に必要
public class BusinessTest{
@InjectMocks
Business business = new Business();
@Mock
Service serviceMock;
//これで、businessのserviceはMockになる。
}
4.when thenReturnの特性
複数のthenReturnが存在する場合、実行された順番にreturnされる
//returnを順番に返す
when(mock.size()).thenReturn(5).thenReturn(10);
assertEquals(5, mock.size()); //true
assertEquals(10, mock.size()); //true
//関数の引数も対応する必要がある
when(mock.get(0)).thenReturn(5);
assertEquals(5, mock.get(0)); //true
assertEquals(5, mock.get(1)); //false
他のツール
①MockitoのAnyパラメータ
//anyInt,anyStringなどもある
import static org.mockito.ArgumentMatchers.anyInt;
when(mock.get(anyInt())).thenReturn("in28Minutes");
②verify
mock内の関数が実行されたかどうかを判断する
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.times;
@Test
public void verificationBasics() {
// SUT
String value1 = mock.get(0);
String value2 = mock.get(1);
// Verify
verify(mock).get(0);
verify(mock, times(2)).get(anyInt()); //2回実行したか
verify(mock, atLeast(1)).get(anyInt()); //最低1回実行したか
verify(mock, atLeastOnce()).get(anyInt()); //最低1回実行したか
verify(mock, atMost(2)).get(anyInt()); //最多2回実行したか
verify(mock, never()).get(2); //実行しなかったか
}
③渡した引数をキャプチャする
import org.mockito.ArgumentCaptor;
@Test
public void argumentCapturing() {
mock.add("SomeString");
//Stringのクラスの引数をキャプチャしたいと設定する
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(mock).add(captor.capture());
assertEquals("SomeString", captor.getValue());
}
//複数の引数の場合
mock.add("SomeString1");
mock.add("SomeString2");
//Stringのクラスの引数をキャプチャしたいと設定する
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(mock, times(2)).add(captor.capture());
List<String> allValues = captor.getAllValues();
assertEquals("SomeString1", allValues.get(0));
assertEquals("SomeString2", allValues.get(1));