Mocking con Mockito
Isoli le dipendenze con Mockito e MockK. Configuri i valori restituiti, verifichi le interazioni, acquisisca gli argomenti e usi gli spy per il mocking parziale.
Mocking con Mockito è una lezione Android Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Android Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Android Academy include 4 lezioni in totale.
Che cos'è il mocking?
Un mock è un oggetto fittizio che sostituisce una dipendenza reale nei test. A differenza di un Fake (un'implementazione funzionante in memoria), un mock:
- Viene generato automaticamente da una libreria
- Registra quali metodi sono stati chiamati e con quali argomenti
- Restituisce ciò che si specifica (stubbing)
- Consente di verificare le interazioni dopo il test
Configurazione di Mockito
Aggiunga Mockito e MockK (l'alternativa pensata per Kotlin) a app/build.gradle:
// app/build.gradle:
testImplementation 'org.mockito:mockito-core:5.10.0'
testImplementation 'org.mockito.kotlin:mockito-kotlin:5.2.1'
// MockK (Kotlin-idiomatic alternative to Mockito):
testImplementation 'io.mockk:mockk:1.13.10'Creazione dei Mock
Crei i mock con mock() o con l'annotazione @Mock:
import org.mockito.kotlin.*
interface UserApi {
suspend fun fetchUsers(): List<User>
suspend fun deleteUser(id: Int)
}
class RepositoryTest {
// Option 1: create inline
private val api: UserApi = mock()
// Option 2: use annotation + MockitoJUnit4Runner
@Mock lateinit var api2: UserApi
@get:Rule
val mockitoRule = MockitoJUnit.rule()
}Stubbing — definizione dei valori restituiti
Utilizzi whenever(mock.method()).thenReturn(value) per impostare il valore restituito da un mock:
val api: UserApi = mock()
// Stub a return value:
whenever(api.fetchUsers()).thenReturn(
listOf(User(1, "Alice"), User(2, "Bob"))
)
// Stub an exception:
whenever(api.fetchUsers()).thenThrow(RuntimeException("Network error"))
// Return different values on consecutive calls:
whenever(api.fetchUsers())
.thenReturn(emptyList()) // first call
.thenReturn(listOf(User(1, "Alice"))) // second callverify() — verifica delle interazioni
Utilizzi verify() per asserire che un metodo sia stato chiamato e quante volte:
val api: UserApi = mock()
val repo = UserRepository(api)
repo.refreshUsers()
// Verify that fetchUsers() was called exactly once:
verify(api).fetchUsers()
// Verify called with specific argument:
repo.deleteUser(42)
verify(api).deleteUser(42)
// Verify called exactly 3 times:
verify(api, times(3)).fetchUsers()
// Verify never called:
verify(api, never()).deleteUser(any())ArgumentCaptor
ArgumentCaptor acquisisce l'argomento passato a un metodo mock, permettendo di asserirne il valore:
val api: UserApi = mock()
val captor = argumentCaptor<User>()
val repo = UserRepository(api)
repo.saveUser(User(1, "Alice"))
verify(api).saveUser(captor.capture())
val captured = captor.firstValue
assertEquals(1, captured.id)
assertEquals("Alice", captured.name)MockK — mocking pensato per Kotlin
MockK è progettato per Kotlin e gestisce nativamente le funzioni di estensione, le coroutine e gli oggetti:
import io.mockk.*
val api = mockk<UserApi>()
// Stub:
every { api.fetchUsers() } returns listOf(User(1, "Alice"))
// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))
// Verify:
val repo = UserRepository(api)
runBlocking { repo.refresh() }
coVerify { api.fetchUsers() }Mocking delle coroutine con MockK
Utilizzi coEvery e coVerify per le funzioni suspend:
val api = mockk<UserApi>()
// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))
coEvery { api.deleteUser(any()) } just Runs // returns Unit
// Test:
runTest {
val repo = UserRepository(api)
repo.refresh()
coVerify(exactly = 1) { api.fetchUsers() }
coVerify(exactly = 0) { api.deleteUser(any()) }
}Spy — mocking parziale
Uno spy avvolge un oggetto reale. Per impostazione predefinita, vengono chiamati i metodi reali, a meno che non vengano sovrascritti:
// Mockito Spy:
val realList = mutableListOf("a", "b", "c")
val spyList = spy(realList)
// Real method called:
spyList.add("d")
assertEquals(4, spyList.size) // real add() was called
// Override specific method:
doReturn(99).`when`(spyList).size
assertEquals(99, spyList.size) // overridden
// MockK Spy:
val spyObj = spyk(RealService())
every { spyObj.expensiveCall() } returns "fake result"Quando utilizzare Mock o Fake
Linee guida pratiche:
- Utilizzi un Fake quando serve un'implementazione funzionante in memoria (DAO, repository): è più facile da leggere e non richiede librerie
- Utilizzi un Mock quando deve verificare che un metodo specifico sia stato chiamato con argomenti specifici (eventi di analytics, chiamate API)
- Eviti il mocking eccessivo: se esegue il mock di tutto, i test verificano i mock e non la logica
Errori comuni
Problemi da evitare nel mocking:
- Fare il mock degli oggetti valore — esegua il mock di interfacce o astrazioni, non delle data class
- Fare il mock a una profondità eccessiva — se in un test servono 5 mock, il codice è troppo accoppiato
- Non verificare quando l'interazione è importante: non si limiti allo stubbing, verifichi anche
- Mockito e i valori predefiniti di Kotlin — i parametri Kotlin non ammettono valori null per impostazione predefinita; utilizzi
mockito-kotlino MockK per evitare sorprese legate a null
Mocking di oggetti e companion object
MockK può eseguire il mock degli oggetti Kotlin e dei companion object, cosa impossibile con Mockito:
object DateProvider {
fun today(): String = "2024-01-01"
}
// In test:
mockkObject(DateProvider)
every { DateProvider.today() } returns "2099-12-31"
val result = DateProvider.today()
assertEquals("2099-12-31", result)
// Restore after test:
unmockkObject(DateProvider)Verifica rapida
Qual è lo scopo di verify() in un test Mockito o MockK?
Riepilogo: mocking con Mockito e MockK
I mock consentono di isolare e verificare il comportamento:
mock()/mockk()— crea un mock a partire da un'interfaccia o da una classewhenever(...).thenReturn(...)/every { } returns ...— definisce i valori restituiticoEvery/coVerify— per le funzioni Kotlin suspend (MockK)verify(mock).method(args)— asserisce che il metodo sia stato chiamatoArgumentCaptor— acquisisce ed esamina gli argomentispy()/spyk()— mock parziale di un oggetto reale- Preferisca i Fake per i dati; utilizzi i Mock per verificare il comportamento
Prossimo argomento: test dell'interfaccia utente con Espresso.
Domande Frequenti
La lezione «Mocking con Mockito» è gratuita?
Sì — il testo completo di «Mocking con Mockito» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Android Academy, passa a CoddyKit PRO. Il corso Android Academy include 4 lezioni in totale.
Cosa imparerò in «Mocking con Mockito»?
Isoli le dipendenze con Mockito e MockK. Configuri i valori restituiti, verifichi le interazioni, acquisisca gli argomenti e usi gli spy per il mocking parziale. Eserciti Android Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Android Academy?
Non è richiesta alcuna esperienza precedente. Android Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Mocking con Mockito»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Android Academy?
Sì. Ogni lezione Android Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Test unitari con JUnit
- Mocking con Mockito
- Test dell'interfaccia con Espresso
- Debug e profiling