Anıl Şenocak

Mockito'da, bir metod çağrıldığında ne döndürüleceğini belirtebiliriz. Bu, mevcut sınıfları değiştirmemiz gerekmediğinden unit testleri kolaylaştırır. Mockito, bunu yapmanın iki yolunu destekler: when-thenReturn ve doReturn-when. Çoğu durumda, when-thenReturn kullanılır ve daha iyi okunabilirliğe sahiptir.
User user = Mockito.mock(User.class);
when(user.getName()).thenReturn("John");
Ancak, bazen farklı davranışlar olduğu için doReturn-when kullanmayı düşünmemiz gerekir.
doReturn parametresi, thenReturn'den farklı olarak Object'tir. Bu nedenle, derleme zamanında tür denetimi yoktur. Çalışma zamanında tür eşleşmediğinde, bir WrongTypeOfReturnValue exception fırlatır.
doReturn(true).when(user).getName());
when-thenReturn'ün mümkünse daha iyi bir seçenek olmasının ana nedeni budur.
Tip güvenliği olmamasına rağmen doReturn-when'ın avantajı yan etkisi olmamasıdır. Mockito'da, gerçek yöntem çağrısına bir yan etki olur. Bunu anlamak için, gerçek bir metot çağırmanın ne zaman gerçekleştiğini bilmemiz gerekir.
Genellikle, bir dönüş değeri belirtmeden önce Mockito.mock ile bir mock nesne oluşturmamız gerekir. Mock nesnenin bir yöntemini çağırdığımızda, belirtilen bir değer döndürür ancak sınıfta tanımladığınız hiçbir şeyi yapmaz. Hiçbir yan etkisi yoktur, bu nedenle when-thenReturn ve doReturn-when'ün bir tür güvenliği olması dışında hemen hemen aynı şekilde davranır.
User user = Mockito.mock(User.class);
when(user.getName()).thenReturn("Lorem");
doReturn(true).when(user).getName());
Fark, Mockito.spy ile bir spy oluşturduğunuzda ortaya çıkar. Bir spy nesne gerçek bir nesneye bağlanır. Bu nedenle, bir yöntemi çağırdığınızda gerçek bir yöntem çağrısı vardır. Bu, when-thenReturn yaptığımızda bile geçerlidir. Bunun nedeni when parametresidir ve bir yöntemi çağırmanın bir yolunu içerir. Örneğin; user.getName(). Buna karşılık, doReturn-when kullandığınızda when parametresi yalnızca user olduğunda geçerlidir.
User user = Mockito.spy(new User());
Bir yan etki her zaman olmaz, ancak olağan durumlar şunlardır:
Bir yöntem, ön koşul denetimiyle bir exception atar. Birim testi yaparken bir yöntem istemediğinizi yapar. Örneğin, ağ veya disk erişimi. Örneğin, liste daha küçükse List#get() bir istisna atar. doReturn, istisna olmadan bir değer belirtebilir.
List list = new LinkedList();
List spy = spy(list);
// Problem: gerçek yöntem spy.get(0) olarak adlandırılır ve IndexOutOfBoundsException'ı atar (liste henüz boş)
when(spy.get(0)).thenReturn("foo");
// Stubbing için doReturn() kullanmalıyız
doReturn("foo").when(spy).get(0);
Başka bir örnek, birim testi için bir sınıf davranışını değiştirmektir. AccountService, test edilecek bir hedeftir, bu nedenle mocklanamaz. Mocktio.spy ve doReturn(), ağ erişimi olmadan birim testi yapabilirsiniz.
public class AccountService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
if("DELETE".equals(intent.getAction())) {
sendDeleteRequest();
}
}
protected void sendDeleteRequest() {
// Network access
}
}
@RunWith(RobolectricTestRunner.class)
public class AccountServiceTest {
@Test
public void shouldSendDeleteRequest_whenDeleteAction() {
AccountService accountService = spy(new AccountService("Account"));
doNothing().when(accountService).sendDeleteRequest();
accountService.onHandleIntent(new Intent("DELETE"));
verify(accountService).sendDeleteRequest();
}
}
Herhangi bir yan etki yoksa, spy nesnesi için when-thenReturn'ü kullanabiliriz.
User user = Mockito.spy(new User());
when(user.getName()).thenReturn("John");
when(...) thenReturn(...), belirtilen değer döndürülmeden hemen önce gerçek bir metod çağrısı yapar. Yani çağrılan metod bir exception atarsa, onunla uğraşmamız gerekir.
doReturn(...) when(...), metod çağrısı yapmaz.
public class TestClass {
protected String testEdilecekMetod() {
throw new NullPointerException();
}
}
@Spy
TestClass testClass;
// metodu çağırmadığı için çalışır
doReturn("test").when(testClass).testEdilecekMetod();
// metod'u çağırdığı için NullPointerException fırlatır
when(testClass.testEdilecekMetod()).thenReturn("test");
doReturn-when, spy yapılan bir nesne üzerinde bir yan etki yaratmadan bir dönüş değeri belirtmek için kullanabiliriz. Yararlıdır, ancak nadiren kullanılmalıdır. MVP, MVVM ve dependency injection gibi daha iyi bir kalıbınız ne kadar fazlaysa, Mockito.spy'ı kullanma şansınız o kadar az olur. Ardından, daha güvenli ve okunabilir olan Mockito.mock kullanabilirsiniz.