Mockito is een open-source framework voor het maken van mock-objecten in eenheidstests in Java en Kotlin, waarmee de geteste code kan worden geïsoleerd van externe afhankelijkheden. Hiermee vervangt de ontwikkelaar echte repositories, API-clients en databases door beheersbare neppers met een ingesteld gedrag. Volgens Mockito.org wordt de bibliotheek gebruikt in meer dan 60% van de Java-projecten die eenheidstests toepassen.
Belangrijkste punten
Mockito is een open-source bibliotheek voor het maken van mock-objecten (neppers) in eenheidstests in Java, Kotlin en andere JVM-talen. In tegenstelling tot JUnit, dat verantwoordelijk is voor het uitvoeren van tests, lost Mockito het probleem van isolatie op — het vervangt de echte afhankelijkheden van de geteste klasse door voorspelbare objecten.
Zonder mocks vereist het testen van een methode die een database of externe API benadert het opzetten van een echte omgeving — het implementeren van een DB, het starten van een server. Mockito vervangt deze afhankelijkheden door objecten met vast gedrag: de methode repository.findById(1) retourneert altijd een specifiek User-object, zonder de database te benaderen.
De architectuur van Mockito is gebaseerd op het Proxy-patroon (voor interfaces en klassen). De bibliotheek genereert een subklasse of proxy voor het opgegeven type en onderschept alle methodeaanroepen, waarbij standaardwaarden of waarden worden geretourneerd die zijn ingesteld via when().thenReturn().
Het werkingsprincipe van Mockito is gebaseerd op drie basisbewerkingen: het maken van een mock, het configureren van gedrag (stubbing) en het verifiëren van aanroepen (verification). Elke bewerking gebruikt statische methoden uit de klasse org.mockito.Mockito — de meest geladen klasse in het Java-ecosysteem volgens Maven Central-statistieken. Alle aanroepen van mock-methoden worden in het geheugen geregistreerd, waardoor ze later via verify kunnen worden gecontroleerd.
Een typische test met Mockito bestaat uit drie fasen: Arrange — het maken van mocks en configureren van stubs via when().thenReturn(), Act — het aanroepen van de geteste methode, Assert — het controleren van het resultaat via assertEquals en verify(mock). Deze aanpak heet AAA (Arrange-Act-Assert).
Laten we een eenvoudige test bekijken waarin Mockito de gebruikersrepository vervangt. De methode when().thenReturn() configureert de mock zo dat de aanroep findById een vooraf voorbereid User-object retourneert.
// We maken een mock van de repository
UserRepository mockRepo = mock(UserRepository.class);
// Configureren gedrag: bij findById(1) de gebruiker retourneren
when(mockRepo.findById(1)).thenReturn(new User("Alice"));
// Controleren of de methode daadwerkelijk is aangeroepen
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);
Mockito biedt twee manieren om mocks te maken: de statische methode mock(Class) en de annotatie @Mock met initialisatie via MockitoAnnotations.openMocks(). De eerste manier is compact voor één of twee mocks, de tweede is handig wanneer er veel afhankelijkheden zijn — annotaties verminderen boilerplate-code.
De methode mock() neemt een klasse en retourneert een nepperd die kan worden geconfigureerd via when().thenReturn(). Alle niet-geconfigureerde methoden retourneren standaardwaarden: 0 voor getallen, false voor boolean, null voor objecten.
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);
De annotatie @Mock in combinatie met @ExtendWith(MockitoExtension.class) maakt automatisch mocks voor alle velden van de testklasse. De extensie MockitoExtension zorgt voor initialisatie vóór elke test.
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void getUserShouldReturnUserFromRepo() {
when(userRepository.findById(1)).thenReturn(new User("Alice"));
User result = userService.getUser(1);
assertEquals("Alice", result.getName());
}
}
Stubbing — het proces van bepalen wat een mock-methode moet retourneren bij aanroep met specifieke argumenten. Basissyntaxis: when(mock.method(args)).thenReturn(value). Voor verschillende scenario's biedt Mockito meerdere varianten van then-methoden.
| Methode | Doel |
|---|---|
| thenReturn(value) | Retourneert altijd de opgegeven waarde |
| thenThrow(exception) | Gooit een uitzondering bij aanroep |
| thenAnswer(answer) | Berekent de retourwaarde dynamisch |
| thenCallRealMethod() | Roept de echte methode aan (gedeeltelijke mock) |
Wanneer de retourwaarde afhankelijk is van de aanroepargumenten, wordt thenAnswer met een lambda gebruikt. Dit is handig voor het simuleren van werken met echte gegevens — bijvoorbeeld het genereren van een ID op basis van het doorgegeven object.
when(repository.save(any())).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(42);
return user;
});
Verify is een unieke mogelijkheid van Mockito die oudere mock-objectbibliotheken (EasyMock, jMock) niet bieden.
Verify maakt tests betrouwbaarder, omdat het niet alleen de retourwaarde controleert, maar ook neveneffecten — aanroepen van methoden die geen resultaat retourneren (void-methoden). De methode verify(mock).methodName(args) controleert of een specifieke mock-methode met de opgegeven argumenten is aangeroepen. Dit maakt het mogelijk om niet alleen het resultaat te testen, maar ook het proces — het feit dat de afhankelijkheid is benaderd.
Standaard controleert verify of een methode precies één keer is aangeroepen. Als een ander aantal nodig is — wordt times(n), atLeast(n), never() en andere modificatoren uit de klasse Mockito gebruikt.
// Aantal aanroepen controleren
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);
// Volgorde van aanroepen controleren
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();
Wanneer moet worden gecontroleerd met welk exact object een methode is aangeroepen, wordt ArgumentCaptor gebruikt. Deze legt de waarde van het argument vast tijdens de aanroep en maakt het mogelijk de velden afzonderlijk te controleren. ArgumentCaptor is vooral handig wanneer de geteste code een object intern aanmaakt en dit doorgeeft aan de afhankelijkheid — u kunt dit object niet op een andere manier controleren.
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());
@Mock en @InjectMocks — twee belangrijke annotaties van Mockito die boilerplate-code aanzienlijk verminderen. @Mock maakt een mock voor een veld, en @InjectMocks injecteert alle mocks uit de testklasse in het geteste object via constructor, setter of veld.
Het mechanisme @InjectMocks probeert afhankelijkheden in de volgende volgorde te injecteren: constructor met het grootste aantal argumenten, setter op type, privé-veld. Als geen enkele manier werkt — blijft het object met null-afhankelijkheden achter en faalt de test met een NullPointerException.
Het is belangrijk te begrijpen: @InjectMocks analyseert geen veldtypen — het plaatst elke mock die compatibel is met het type. Als een klasse twee velden van hetzelfde type heeft — kan Mockito de verkeerde mock injecteren. In dergelijke gevallen wordt aanbevolen een expliciete constructor te gebruiken met het doorgeven van mocks.
In Android-ontwikkeling wordt Mockito samen met JUnit gebruikt voor het testen van ViewModel, Repository en UseCase. Omdat deze klassen op de JVM draaien zonder Android-context, vervangt Mockito hun afhankelijkheden — Room DAO, Retrofit API, SharedPreferences — door stubs met voorspelbaar gedrag.
Om Mockito aan een Android-project toe te voegen, volstaat het om de afhankelijkheid mockito-core of mockito-inline toe te voegen (de laatste ondersteunt het mocken van final-klassen en statische methoden). Versie 5.12.0 (2024) bevat ondersteuning voor Java 21 en verbeterde integratie met JUnit 5.
// build.gradle.kts (module)
dependencies {
testImplementation("org.mockito:mockito-core:5.12.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}
Vroeger was voor het mocken van statische methoden en constructoren PowerMock nodig — een extensie die werkte via bytecode-instrumentatie. Sinds Mockito 5.x met mockito-inline is deze functionaliteit direct ingebouwd: mockStatic(ClassName.class) maakt het mogelijk statische methoden te mocken zonder extra bibliotheken.
Typisch scenario: ViewModel roept een repository-methode aan en transformeert het resultaat naar een UI-status. Mockito vervangt de repository en de test controleert of de ViewModel de succesvolle respons en fout correct verwerkt. Bij gebruik van Clean Architecture worden mocks gemaakt voor elke laag: DataSource, Repository en UseCase — dit maakt het mogelijk elke laag geïsoleerd te testen.
Veelgestelde vragen
Mockito is een bibliotheek voor Java en Kotlin die proxy en reflectie gebruikt. MockK is een Kotlin-first bibliotheek met ondersteuning voor coroutines, extensiefuncties en final-klassen zonder extra configuratie.
Sinds Mockito 2.1 wordt het mocken van final-klassen ondersteund via opt-in. In versie 5.x (mockito-inline) is dit standaard ingeschakeld. Voeg gewoon de afhankelijkheid mockito-inline toe en gebruik de standaard mock()-methode.
Spy is een gedeeltelijke mock die standaard echte methoden aanroept, maar het mogelijk maakt sommige ervan te overschrijven via when().thenReturn(). Spy is nuttig voor het testen van legacy-code wanneer de hele klasse niet kan worden herschreven.
thenReturn retourneert altijd dezelfde waarde, ongeacht de argumenten. thenAnswer berekent de retourwaarde op basis van de aanroep — argumenten, de mock zelf, status. Gebruik voor dynamische antwoorden altijd thenAnswer.
Verify controleert niet alleen het resultaat, maar ook het proces — het feit dat de afhankelijkheid is benaderd. Dit is cruciaal voor services die gegevens moeten opslaan of meldingen moeten verzenden. Zonder verify zal de test niet ontdekken dat de methode save() of send() niet heeft aangeroepen.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook