Anıl Şenocak

In Mockito können wir festlegen, was zurückgegeben werden soll, wenn eine Methode aufgerufen wird. Dies erleichtert Unit-Tests, da wir die bestehenden Klassen nicht ändern müssen. Mockito unterstützt zwei Möglichkeiten, dies zu tun: when-thenReturn und doReturn-when. In den meisten Fällen wird when-thenReturn verwendet, da es eine bessere Lesbarkeit bietet.
User user = Mockito.mock(User.class);
when(user.getName()).thenReturn("John");
Manchmal müssen wir jedoch die Verwendung von doReturn-when in Betracht ziehen, da es ein anderes Verhalten aufweist.
Der Parameter von doReturn ist im Gegensatz zu thenReturn ein Object. Daher gibt es zur Kompilierzeit keine Typprüfung. Wenn der Typ zur Laufzeit nicht übereinstimmt, wird eine WrongTypeOfReturnValue-Exception ausgelöst.
doReturn(true).when(user).getName());
Dies ist der Hauptgrund, warum when-thenReturn nach Möglichkeit die bessere Wahl ist.
Trotz der fehlenden Typsicherheit liegt der Vorteil von doReturn-when darin, dass es keine Nebenwirkungen hat. In Mockito kann ein realer Methodenaufruf Nebenwirkungen haben. Um dies zu verstehen, müssen wir wissen, wann ein echter Methodenaufruf stattfindet.
Normalerweise müssen wir ein Mock-Objekt mit Mockito.mock erstellen, bevor wir einen Rückgabewert festlegen. Wenn wir eine Methode des Mock-Objekts aufrufen, gibt sie einen bestimmten Wert zurück, führt aber nichts aus, was in der Klasse definiert ist. Es gibt keine Nebenwirkungen, sodass sich when-thenReturn und doReturn-when fast identisch verhalten, abgesehen von der Typsicherheit.
User user = Mockito.mock(User.class);
when(user.getName()).thenReturn("Lorem");
doReturn(true).when(user).getName());
Der Unterschied zeigt sich, wenn Sie einen Spy mit Mockito.spy erstellen. Ein Spy-Objekt ist an ein reales Objekt gebunden. Daher erfolgt beim Aufruf einer Methode ein echter Methodenaufruf. Dies gilt auch dann, wenn wir when-thenReturn verwenden. Der Grund dafür ist der when-Parameter, der einen Weg zum Aufrufen einer Methode enthält. Zum Beispiel: user.getName(). Im Gegensatz dazu ist bei der Verwendung von doReturn-when der Parameter von when nur das user-Objekt selbst.
User user = Mockito.spy(new User());
Eine Nebenwirkung tritt nicht immer auf, aber typische Fälle sind:
List#get() eine Exception, wenn die Liste zu klein ist. Mit doReturn kann ein Wert ohne Exception festgelegt werden.List list = new LinkedList();
List spy = spy(list);
// Problem: Die echte Methode spy.get(0) wird aufgerufen und wirft eine IndexOutOfBoundsException (da die Liste noch leer ist)
when(spy.get(0)).thenReturn("foo");
// Wir müssen doReturn() für das Stubbing verwenden
doReturn("foo").when(spy).get(0);
Ein weiteres Beispiel ist das Ändern des Verhaltens einer Klasse für Unit-Tests. AccountService ist das zu testende Ziel (Target under Test) und kann daher nicht gemockt werden. Mit Mockito.spy und doReturn() können Sie Unit-Tests ohne Netzwerkzugriff durchführen.
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();
}
}
Wenn keine Nebenwirkungen vorliegen, können wir when-thenReturn für das Spy-Objekt verwenden.
User user = Mockito.spy(new User());
when(user.getName()).thenReturn("John");
when(...) thenReturn(...) führt einen echten Methodenaufruf durch, kurz bevor der angegebene Wert zurückgegeben wird. Wenn die aufgerufene Methode also eine Exception wirft, müssen wir uns darum kümmern.
doReturn(...) when(...) führt keinen Methodenaufruf durch.
public class TestClass {
protected String testEdilecekMetod() {
throw new NullPointerException();
}
}
@Spy
TestClass testClass;
// Funktioniert, da die Methode nicht aufgerufen wird
doReturn("test").when(testClass).testEdilecekMetod();
// Wirft NullPointerException, da die Methode aufgerufen wird
when(testClass.testEdilecekMetod()).thenReturn("test");
Wir können doReturn-when verwenden, um einen Rückgabewert festzulegen, ohne eine Nebenwirkung auf einem Spy-Objekt zu erzeugen. Es ist nützlich, sollte aber selten verwendet werden. Je mehr Sie bewährte Entwurfsmuster wie MVP, MVVM und Dependency Injection nutzen, desto seltener müssen Sie Mockito.spy verwenden. Stattdessen können Sie das sicherere und lesbarere Mockito.mock verwenden.