JUnit Mockito — Cheat Sheet

Tag: junit, mockito, java, testing, unit-testing, mocks, stubbing

Livello: intermedio

TL;DR: Riferimento rapido per lo unit testing in Java. Copre l'isolamento delle dipendenze con Mockito e la validazione dei risultati tramite le asserzioni di JUnit.

Concetti chiave

JUnit è il framework di unit testing standard per applicazioni Java.

Mockito permette di creare oggetti mock per isolare il componente in test dalle sue dipendenze.

L'annotazione @Mock genera un'istanza fittizia di una classe o di un'interfaccia.

L'annotazione @InjectMocks istanzia la classe in test e inietta automaticamente i mock nei suoi campi.

Lo stubbing definisce il comportamento simulato dei mock in scenari specifici.

La verifica assicura che il componente abbia interagito correttamente con le sue dipendenze.

L'annotazione @Spy crea un mock parziale, eseguendo i metodi reali a meno di stubbing esplicito.

Le asserzioni validano l'output effettivo del codice rispetto al risultato atteso.

Domande tipiche e risposte pronte

Q: Qual è la differenza tra @Mock e @Spy?R: Uso @Mock per creare un oggetto completamente fittizio con comportamenti vuoti di default. Uso @Spy per avvolgere un'istanza reale e mantenere i comportamenti originali, stubbando solo cio' che mi serve.

Q: Come verifichi che un metodo lanci una specifica eccezione?R: Utilizzo il costrutto assertThrows di JUnit 5, passando la classe dell'eccezione attesa e una lambda che esegue il metodo incriminato.

Q: Come testi un metodo void con Mockito?R: Non potendo verificare il valore di ritorno, uso verify(mock).metodo() per accertarmi che sia stato invocato, oppure doThrow() se devo simulare un'eccezione.

Insidie e errori comuni

Dimenticare di abilitare Mockito nel test tramite @ExtendWith(MockitoExtension.class).

Applicare @InjectMocks su un'interfaccia invece che sull'implementazione concreta da testare.

Tentare di fare stubbing su metodi final, private o static senza aver incluso e configurato mockito-inline.

Usare matcher generici (come any()) insieme a valori espliciti nella stessa chiamata di metodo senza avvolgere i valori in eq().

Snippet e comandiJava

```import static org.mockito.Mockito.*;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.extension.ExtendWith;

import org.mockito.InjectMocks;

import org.mockito.Mock;

import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Optional;

@ExtendWith(MockitoExtension.class)

class UserServiceTest {

@Mock

private UserRepository userRepository;

@InjectMocks

private UserService userService;

@Test

void shouldReturnUserWhenFound() {

// Arrange (Stubbing)

User mockUser = new User("Alice");

when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));

// Act

User result = userService.getUserById(1L);

// Assert

assertEquals("Alice", result.getName());

// Verify

verify(userRepository, times(1)).findById(1L);

}

@Test

void shouldThrowExceptionWhenUserNotFound() {

// Arrange

when(userRepository.findById(2L)).thenReturn(Optional.empty());

// Act & Assert

assertThrows(UserNotFoundException.class, () -> {

userService.getUserById(2L);

});

}

}

```

Jarvis Interviews
Jarvis