webitect.de
Home | Blog | Apps

Veröffentlicht: 16.03.2024

Mockito: Stub/Spy vs Mock

Im Artikel Mockito: Unterschied doReturn ... when und when ... thenReturn hatten wir uns die Vorteile von when...thenReturn im Vergleich zu doReturn...when angeschaut. In diesem Artikel werden wir sehen, dass es für Mockito.spy() einen großen Unterschied macht, welche Variante wir wählen.

1    package de.webitect.mockito;
2    
3    import org.junit.jupiter.api.Test;
4    import org.mockito.Mockito;
5    
6    import static org.hamcrest.MatcherAssert.assertThat;
7    import static org.hamcrest.Matchers.is;
8    import static org.mockito.Mockito.*;
9    
10   public class MockitoTest {
11   
12       @Test
13       void testMocking(){
14           //given
15           final String expectedName = "mockedName";
16           final ClassToTest sut = mock(MockitoTest.ClassToTest.class);
17           when(sut.getName()).thenReturn(expectedName); // läuft!
18           doReturn(expectedName).when(sut).getName(); // läuft!
19   
20           //when
21           final String name = sut.getName();
22   
23           //then
24           assertThat(name, is(expectedName));
25       }
26   
27       @Test
28       void testStubbing(){
29           //given
30           final String expectedName = "stubbedName";
31           final ClassToTest sut = spy(new ClassToTest());
32           when(sut.getName()).thenReturn(expectedName); // NPE
33           doReturn(expectedName).when(sut).getName(); // läuft!
34   
35           //when
36           final String name = sut.getName();
37   
38           //then
39           assertThat(name, is(expectedName));
40       }
41   
42       static class ClassToTest{
43           private final MyObj myObj = null;
44   
45           String getName(){
46               return myObj.name;
47           }
48       }
49   
50       static class MyObj{
51           private final String name = "Hello World";
52       }
53   }
54   

Der Code ist einfach gehalten. Wir wollen die Methode getName() der Klasse ClassToTest testen. Die Methode getName() gibt einen String zurück. Wir sehen leicht, dass das Ausführen zu einer NullPointerException (NPE) führen wird, weil myObj final mit null initialisiert worden ist.
Unsere beiden Testmethoden nutzen einen Mock testMocking() und einen Spy testStubbing(). Im Fall des Mocks können wir beide Varianten nutzen. Sowohl when...thenReturn als auch doReturn...when funktionieren. Nutzen wir einen Stub (spy(new ClassToTest())), wie in unserer zweiten Testmethode, können wir when...thenReturn nicht nutzen, da dies bei der Testausführung zu einer NPE führt:

java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:208)
at de.webitect.mockito.MockitoTest$ClassToTest.getName(MockitoTest.java:46)
at de.webitect.mockito.MockitoTest.testStubbing(MockitoTest.java:32)

Wenn wir also Mockito.spy() nutzen, kann das Verwenden von when...thenReturn unerwartete Nebenwirkungen haben, da wir offensichtlich den Production Code durchlaufen und damit zum Beispiel in unserem Fall die NPE auslösen.

© 2023 - 2025 webitect.de | Impressum | About