---
# System prepended metadata

title: Mockito

---

> [name=Martin. S]
> [time=Thu, Apr 13, 2023]
> [name=Lucas. C]
> [time=Thu, Apr 13, 2023]
> [name=Lukas. B]
> [time=Thu, Apr 13, 2023]
> [name=Linus. S]
> [time=Thu, Apr 13, 2023]

# Mockito
## 1. Grundlagen von Mockito:

-  ist eine Open-Source-Testframework für Java, das verwendet wird, um Mock-Objekte für Unit-Tests zu erstellen.
-  damit können Mock-Objekte erstellt werden, um externe Abhängigkeiten von Unit-Tests zu isolieren und Tests unabhängig und deterministisch zu gestalten.
- ermöglicht das Definieren von Verhalten für Mock-Objekte, wie das Festlegen von Rückgabewerten, das Überprüfen von Methodenaufrufen und das Werfen von Ausnahmen.
-  bietet auch Funktionen zur Überprüfung von Verhalten, wie das Überprüfen von Methodenaufrufen und Argumenten.

## 2. Annotation bei Mockito:
-   **@Mock**: Diese Annotation wird verwendet, um ein Mock-Objekt zu erstellen. Es wird normalerweise für externe Abhängigkeiten verwendet, die in einem Unit-Test simuliert werden sollen.
-   **@Spy**: Diese Annotation wird verwendet, um ein Spy-Objekt zu erstellen. Ein Spy ist ein echtes Objekt, das jedoch überwacht wird und Methodenaufrufe und Rückgabewerte verfolgen kann.
-   **@Captor**: Diese Annotation wird verwendet, um Argumente zu erfassen, die an Mock-Objekte übergeben wurden, wenn Methoden auf ihnen aufgerufen wurden. Es ermöglicht das Überprüfen von Argumenten, die an Mock-Objekte übergeben wurden.
-   **@InjectMock**: Diese Annotation wird verwendet, um ein echtes Objekt zu erstellen, das Mock-Objekte injiziert, um die Abhängigkeiten des zu testenden Objekts zu steuern.

## 3. Unterschied zwischen @Mock und @Spy mit praktischem Beispiel:
-   @Mock erstellt ein vollständig simuliertes Objekt, das kein echtes Verhalten hat und nur definiertes Verhalten gemäß den Tests ausführt.
-   @Spy erstellt ein echtes Objekt, das jedoch überwacht wird und das tatsächliche Verhalten behält, es sei denn, es wird speziell durch Mockito-Anweisungen überschrieben.

### Praktisches Beispiel
UserService Klasse
```java 
public class UserService {
  private UserRepository userRepository;

  // Konstruktor
  public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  // Methode, um einen neuen Benutzer zu speichern
  public void createUser(User user) {
    // Logik zur Erstellung eines Benutzers
    userRepository.save(user);
  }

  // Methode, um einen Benutzer anhand der ID abzurufen
  public User getUserById(int userId) {
    // Logik zur Abfrage eines Benutzers anhand der ID
    return userRepository.findById(userId);
  }
}
```

UserService-Test mit **@Mock**
```java
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

  @Mock
  private UserRepository userRepositoryMock; // Mock-Objekt erstellen

  private UserService userService;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    userService = new UserService(userRepositoryMock);
  }

  @Test
  public void testCreateUser() {
    User user = new User("John", "Doe");
    userService.createUser(user);
    Mockito.verify(userRepositoryMock).save(user); // Überprüfen, ob die Methode save() mit dem richtigen User-Objekt aufgerufen wurde
  }

  @Test
  public void testGetUserById() {
    int userId = 1;
    User expectedUser = new User("John", "Doe");
    Mockito.when(userRepositoryMock.findById(userId)).thenReturn(expectedUser); // Definieren des Rückgabewerts für die Methode findById()
    User actualUser = userService.getUserById(userId);
    assertEquals(expectedUser, actualUser); // Überprüfen, ob der zurückgegebene User dem erwarteten User entspricht
  }
}
``` 

UserService-Test mit **@Spy**
```java
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

  @Spy
  private UserRepository userRepositorySpy; // Spy-Objekt erstellen

  private UserService userService;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    userService = new UserService(userRepositorySpy);
  }

  @Test
  public void testCreateUser() {
    User user = new User("John", "Doe");
    userService.createUser(user);
    Mockito.verify(userRepositorySpy).save(user); // Überprüfen, ob die Methode save() mit dem richtigen User-Objekt aufgerufen wurde
  }

  @Test
  public void testGetUserById() {
    int userId = 1;
    User expectedUser = new User("John", "Doe");
    Mockito.when(userRepositorySpy.findById(userId)).thenReturn(expectedUser); // Definieren des Rückgabewerts für die Methode findById()
    User actualUser = userService
```

## 4. Nutzen des Einsatzes von Mockito in den Unit Tests des Beispielprojektes:

- Code kann mehrfach genutzt werden
- Änderungen können einfacher durchegeführt werden
- Bessere Übersicht

### Before
Ohne die Benutzung von Mockito muss in jedem Test einzeln die Testdaten inizialisiert werden
```java
    @Test
    public void whenGetSortedShapesAsc_thenReturnCorrectAscSort() {
        // arrange
        ShapeSorter sorter = new ShapeSorter();
        Rectangle rect1 = new Rectangle(0, 0, 10, 10);
        Rectangle rect2 = new Rectangle(0, 0, 20, 20);
        Rectangle rect3 = new Rectangle(0, 0, 15, 15);
        Rectangle rect4 = new Rectangle(0, 0, 5, 5);
        Rectangle rect5 = new Rectangle(0, 0, 12, 12);

        sorter.addShapeToSort(rect1);
        sorter.addShapeToSort(rect2);
        sorter.addShapeToSort(rect3);
        sorter.addShapeToSort(rect4);
        sorter.addShapeToSort(rect5);

        // act
        List<ShapeWithArea> result = sorter.getSortedShapesAsc();

        // assert
        assertEquals(rect4.calculateArea(), result.get(0).calculateArea(), 0);
        assertEquals(rect1.calculateArea(), result.get(1).calculateArea(), 0);
        assertEquals(rect5.calculateArea(), result.get(2).calculateArea(), 0);
        assertEquals(rect3.calculateArea(), result.get(3).calculateArea(), 0);
        assertEquals(rect2.calculateArea(), result.get(4).calculateArea(), 0);
    }
```

### After (With Mockito)
Mit Mockitp werden die Testdaten einmal in einer Setup funktion inizialisiert.
```java
      @Mock
    ShapeWithArea shape1;

    @Mock
    ShapeWithArea shape2;

    @Mock
    ShapeWithArea shape3;

    @Mock
    ShapeWithArea shape4;

    @Mock
    ShapeWithArea shape5;

    @Spy
    ShapeSorter sorter;

    @BeforeEach
    public void setup() {
        // arrange
        sorter = spy(new ShapeSorter());

        sorter.addShapeToSort(shape1);
        sorter.addShapeToSort(shape2);
        sorter.addShapeToSort(shape3);
        sorter.addShapeToSort(shape4);
        sorter.addShapeToSort(shape5);

        lenient().when(shape1.calculateArea()).thenReturn(100d);
        lenient().when(shape2.calculateArea()).thenReturn(400d);
        lenient().when(shape3.calculateArea()).thenReturn(225d);
        lenient().when(shape4.calculateArea()).thenReturn(25d);
        lenient().when(shape5.calculateArea()).thenReturn(144d);
    }
```

# Teil 2 Praxis :smiling_face_with_smiling_eyes_and_hand_covering_mouth: 

## 1. & 2.
1. Ist vorbereitung für 2.
Mockito optimiert den Test, indem es Argument Matchers verwendet, um flexible Erwartungen für Methodenaufrufe zu setzen und den Testcode weniger anfällig für Änderungen in den Argumenten zu machen. Ausserdem kann Mockito Verify verwenden, um sicherzustellen, dass bestimmte Methodenaufrufe mit den erwarteten Argumenten aufgerufen wurden.


## 3.
Neuer Test mit @Mock und @Spy Annotations erstellt.

```java
@RunWith(MockitoJUnitRunner.class)
public class LanguageControllerTestMock {

    @Mock
    private LanguageRepository languageRepository;

    @InjectMocks
    private LanguageController languageController;

    @Spy
    private List<Language> languages = new LinkedList<>();

    @Test
    public void testGetAllLanguages() {
        Language language1 = new Language("Englisch");
        Language language2 = new Language("Spanisch");
        languages.add(language1);
        languages.add(language2);

        Mockito.when(languageRepository.findAll()).thenReturn(languages);
        
        ResponseEntity<Iterable<Language>> response = languageController.getAllLanguages();
        
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    	assertThat(response.getBody()).hasSize(2);
    	assertThat(response.getBody()).contains(language1, language2);

    	Mockito.verify(languageRepository).findAll();
    }
}



```