Mockito är ett ramverk med öppen källkod för att skapa mock-objekt i enhetstester i Java och Kotlin, som gör det möjligt att isolera den testade koden från externa beroenden. Med dess hjälp ersätter utvecklaren riktiga repositories, API-klienter och databaser med kontrollerade substitut med specificerat beteende. Enligt data från Mockito.org används biblioteket i mer än 60% av Java-projekt som tillämpar enhetstestning.
Huvudpunkter
Mockito är ett bibliotek med öppen källkod för att skapa mock-objekt (substitut) i enhetstester i Java, Kotlin och andra JVM-språk. Till skillnad från JUnit, som ansvarar för att köra tester, löser Mockito problemet med isolering — det ersätter de verkliga beroendena för den testade klassen med förutsägbara objekt.
Utan mockar kräver testning av en metod som använder en databas eller ett externt API att man sätter upp en verklig miljö — driftsätta databasen, starta en server. Mockito ersätter dessa beroenden med objekt med fast beteende: metoden repository.findById(1) returnerar alltid ett specifikt User-objekt utan att gå till databasen.
Arkitekturen för Mockito bygger på mönstret Proxy (för gränssnitt och klasser). Biblioteket genererar en underklass eller proxy för den angivna typen och fångar upp alla metodanrop, och returnerar standardvärden eller värden som ställts in via when().thenReturn().
Funktionsprincipen för Mockito bygger på tre grundläggande operationer: skapa mock, konfigurera beteende (stubbing) och verifiera anrop (verification). Varje operation använder statiska metoder från klassen org.mockito.Mockito — den mest laddade klassen i Java-ekosystemet enligt Maven Central-statistik. Alla anrop av mock-metoder registreras i minnet, vilket gör att de senare kan kontrolleras via verify.
Ett typiskt test med Mockito består av tre faser: Arrange — skapa mockar och konfigurera stubs via when().thenReturn(), Act — anropa den testade metoden, Assert — kontrollera resultatet via assertEquals och verify(mock). Detta tillvägagångssätt kallas AAA (Arrange-Act-Assert).
Låt oss titta på ett enkelt test där Mockito ersätter användararkivet. Metoden when().thenReturn() konfigurerar mocken så att anropet findById returnerar ett förberett User-objekt.
// Vi skapar en mock av arkivet
UserRepository mockRepo = mock(UserRepository.class);
// Konfigurerar beteende: vid findById(1) returnera användaren
when(mockRepo.findById(1)).thenReturn(new User("Alice"));
// Kontrollerar att metoden verkligen anropades
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);
Mockito erbjuder två sätt att skapa mockar: den statiska metoden mock(Class) och annoteringen @Mock med initiering via MockitoAnnotations.openMocks(). Det första sättet är kompakt för en-två mockar, det andra är bekvämt när det finns många beroenden — annoteringar minskar boilerplate-kod.
Metoden mock() tar emot en klass och returnerar ett substitutobjekt som kan konfigureras via when().thenReturn(). Alla okonfigurerade metoder returnerar standardvärden: 0 för siffror, false för boolean, null för objekt.
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);
Annoteringen @Mock i kombination med @ExtendWith(MockitoExtension.class) skapar automatiskt mockar för alla fält i testklassen. Tillägget MockitoExtension ansvarar för initiering före varje 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 — processen att bestämma vad en mock-metod ska returnera när den anropas med specifika argument. Grundläggande syntax: when(mock.method(args)).thenReturn(value). För olika scenarier erbjuder Mockito flera varianter av then-metoder.
| Metod | Syfte |
|---|---|
| thenReturn(value) | Returnerar alltid det angivna värdet |
| thenThrow(exception) | Kastar ett undantag vid anrop |
| thenAnswer(answer) | Beräknar returvärdet dynamiskt |
| thenCallRealMethod() | Anropar den verkliga metoden (delvis mock) |
När returvärdet beror på anropsargumenten används thenAnswer med en lambda. Detta är användbart för att simulera arbete med verklig data — till exempel generering av ett ID baserat på det överförda objektet.
when(repository.save(any())).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(42);
return user;
});
Verify är en unik funktion i Mockito som äldre mock-objektbibliotek (EasyMock, jMock) inte erbjuder.
Verify gör tester mer tillförlitliga eftersom det inte bara kontrollerar returvärdet, utan även bieffekter — anrop av metoder som inte returnerar något resultat (void-metoder). Metoden verify(mock).methodName(args) kontrollerar om en specifik mock-metod anropades med de angivna argumenten. Detta gör det möjligt att testa inte bara resultatet, utan även processen — faktumet att beroendet användes.
Som standard kontrollerar verify att metoden anropades exakt en gång. Om ett annat antal behövs — används times(n), atLeast(n), never() och andra modifierare från klassen Mockito.
// Kontrollera antalet anrop
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);
// Kontrollera ordningen på anrop
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();
När man behöver kontrollera med vilket exakt objekt metoden anropades, används ArgumentCaptor. Den fångar argumentets värde under anropet och gör det möjligt att kontrollera dess fält separat. ArgumentCaptor är särskilt användbar när den testade koden skapar ett objekt internt och skickar det till beroendet — du kan inte kontrollera detta objekt på annat sätt.
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());
@Mock och @InjectMocks — två viktiga annoteringar i Mockito som avsevärt minskar boilerplate-kod. @Mock skapar en mock för ett fält, och @InjectMocks injicerar alla mockar från testklassen i det testade objektet via konstruktor, setter eller fält.
Mekanismen @InjectMocks försöker injicera beroenden i följande ordning: konstruktor med flest argument, setter efter typ, privat fält. Om ingen metod fungerar — förblir objektet med null-beroenden och testet misslyckas med NullPointerException.
Det är viktigt att förstå: @InjectMocks analyserar inte fälttyper — den sätter in vilken mock som helst som är typkompatibel. Om en klass har två fält av samma typ — kan Mockito injicera fel mock. I sådana fall rekommenderas att använda en explicit konstruktor med överföring av mockar.
I Android-utveckling används Mockito tillsammans med JUnit för att testa ViewModel, Repository och UseCase. Eftersom dessa klasser körs på JVM utan Android-kontext, ersätter Mockito deras beroenden — Room DAO, Retrofit API, SharedPreferences — med stubs med förutsägbart beteende.
För att lägga till Mockito i ett Android-projekt räcker det att lägga till beroendet mockito-core eller mockito-inline (den senare stöder mockning av final-klasser och statiska metoder). Version 5.12.0 (2024) innehåller stöd för Java 21 och förbättrad integration med JUnit 5.
// build.gradle.kts (modul)
dependencies {
testImplementation("org.mockito:mockito-core:5.12.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}
Tidigare krävdes PowerMock för mockning av statiska metoder och konstruktorer — ett tillägg som fungerade via bytekod-instrumentering. Från och med Mockito 5.x med mockito-inline är denna funktionalitet inbyggd direkt: mockStatic(ClassName.class) gör det möjligt att mocka statiska metoder utan extra bibliotek.
Typiskt scenario: ViewModel anropar en metod i arkivet och omvandlar resultatet till UI-tillstånd. Mockito ersätter arkivet och testet kontrollerar att ViewModel korrekt hanterar ett lyckat svar och fel. Vid användning av Clean Architecture skapas mockar för varje lager: DataSource, Repository och UseCase — detta gör det möjligt att testa varje lager isolerat.
Vanliga frågor
Mockito är ett bibliotek för Java och Kotlin som använder proxy och reflektion. MockK är ett Kotlin-first bibliotek med stöd för korutiner, tilläggsfunktioner och final-klasser utan extra konfiguration.
Från och med Mockito 2.1 stöds mockning av final-klasser via opt-in. I version 5.x (mockito-inline) är detta aktiverat som standard. Lägg bara till beroendet mockito-inline och använd standardmetoden mock().
Spy är en delvis mock som som standard anropar verkliga metoder, men gör det möjligt att åsidosätta några av dem via when().thenReturn(). Spy är användbart för att testa äldre kod när hela klassen inte kan skrivas om.
thenReturn returnerar alltid samma värde, oavsett argumenten. thenAnswer beräknar returvärdet baserat på anropet — argument, själva mocken, tillstånd. För dynamiska svar, använd alltid thenAnswer.
Verify kontrollerar inte bara resultatet, utan även processen — faktumet att beroendet användes. Detta är kritiskt för tjänster som måste spara data eller skicka meddelanden. Utan verify kommer testet inte att upptäcka att metoden inte anropade save() eller send().
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också