Mockito — шта је то, кључни појмови и принцип рада

Аутор: IT Sectr Објављено: 2026-04-08 Време читања: 8 мин

Mockito је фрејмворк отвореног кода за креирање мок-објеката у модуларним тестовима Java и Kotlin, који омогућава изолацију тестираног кода од спољашњих зависности. Помоћу њега програмер замењује стварна репозиторијуме, API клијенте и базе података контролисаним заглушкама са задатим понашањем. Према подацима Mockito.org, библиотека се користи у више од 60% Java пројеката који примењују модуларно тестирање.

Главно

  • Mockito — библиотека за креирање мок-објеката који замењују стварне зависности у тестовима.
  • Mock — објекат-заглушка који имитира понашање стварне компоненте.
  • Stubbing — подешавање повратне вредности при позиву метода мока.
  • Verify — провера да ли је метод позван са одређеним аргументима.
  • @InjectMocks — аутоматско убризгавање мок-зависности у тестирани објекат.

Шта је Mockito?

Mockito је библиотека отвореног кода за креирање мок-објеката (заглушки) у модуларним тестовима на Java, Kotlin и другим JVM језицима. За разлику од JUnit, који је одговоран за покретање тестова, Mockito решава проблем изолације — замењује стварне зависности тестиране класе предвидљивим објектима.

Без мокова, тестирање метода који приступа бази података или спољном API-ју захтева подешавање стварног окружења — покретање базе, сервера. Mockito замењује ове зависности објектима са фиксним понашањем: метод repository.findById(1) увек враћа одређени User објекат, без приступа бази.

Архитектура Mockito се заснива на обрасцу Proxy (за интерфејсе и класе). Библиотека генерише подкласу или прокси за наведени тип и пресреће све позиве метода, враћајући подразумеване вредности или вредности задате кроз when().thenReturn().

Како ради Mockito

Принцип рада Mockito се заснива на три основне операције: креирање мока, подешавање понашања (stubbing) и провера позива (verification). Свака операција користи статичке методе из класе org.mockito.Mockito — најоптерећеније класе у екосистему Java према статистици Maven Central. Сви позиви метода мока се бележе у меморији, што омогућава каснију проверу кроз verify.

Три корака теста са Mockito

Типичан тест са Mockito се састоји од три фазе: Arrange — креирање мокова и подешавање стабова кроз when().thenReturn(), Act — позив тестираног метода, Assert — провера резултата кроз assertEquals и verify(mock). Овај приступ се назива AAA (Arrange-Act-Assert).

Основни пример са моком репозиторијума

Размотримо једноставан тест у коме Mockito замењује репозиторијум корисника. Метод when().thenReturn() подешава мок тако да позив findById враћа унапред припремљен User објекат.

java
// Креирамо мок репозиторијума
UserRepository mockRepo = mock(UserRepository.class);

// Подешавамо понашање: при findById(1) врати корисника
when(mockRepo.findById(1)).thenReturn(new User("Alice"));

// Проверавамо да ли је метод стварно позван
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);

Креирање мок-објеката

Mockito пружа два начина креирања мокова: статички метод mock(Class) и анотацију @Mock са иницијализацијом кроз MockitoAnnotations.openMocks(). Први начин је компактан за један-два мока, други је згодан када је зависности много — анотације смањују boilerplate код.

Кроз статички метод mock()

Метод mock() прима класу и враћа објекат-заглушку који се може подесити кроз when().thenReturn(). Сви неподешени методи враћају подразумеване вредности: 0 за бројеве, false за boolean, null за објекте.

java
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);

Кроз анотацију @Mock са JUnit 5

Анотација @Mock у комбинацији са @ExtendWith(MockitoExtension.class) аутоматски креира мокове за сва поља тестне класе. Екстензија MockitoExtension је одговорна за иницијализацију пре сваког теста.

java
@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: подешавање понашања мока

Stubbing — процес одређивања шта метод мока треба да врати при позиву са одређеним аргументима. Основна синтакса: when(mock.method(args)).thenReturn(value). За различите сценарије, Mockito нуди неколико варијанти then-метода.

МетодНамена
thenReturn(value)Увек враћа наведену вредност
thenThrow(exception)Баца изузетак при позиву
thenAnswer(answer)Израчунава повратну вредност динамички
thenCallRealMethod()Позива стварни метод (делимични мок)

Динамички одговор кроз thenAnswer

Када повратна вредност зависи од аргумената позива, користи се thenAnswer са ламбдом. Ово је корисно за имитацију рада са стварним подацима — на пример, генерисање ID-ја на основу прослеђеног објекта.

java
when(repository.save(any())).thenAnswer(invocation -> {
    User user = invocation.getArgument(0);
    user.setId(42);
    return user;
});

Verify: провера интеракција са моком

Verify је јединствена могућност Mockito-а коју старије библиотеке мок-објеката (EasyMock, jMock) не пружају.

Verify чини тестове поузданијим, јер проверава не само повратну вредност, већ и споредне ефекте — позиве метода који не враћају резултат (void методи). Метод verify(mock).methodName(args) проверава да ли је одређени метод мока позван са наведеним аргументима. Ово омогућава тестирање не само резултата, већ и процеса — чињенице обраћања зависности.

Провера броја позива

Подразумевано, verify проверава да је метод позван тачно једанпут. Ако је потребан други број — користе се times(n), atLeast(n), never() и други модификатори из класе Mockito.

java
// Провера броја позива
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);

// Провера редоследа позива
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();

ArgumentCaptor за хватање аргумената

Када треба проверити са којим тачно објектом је метод позван, користи се ArgumentCaptor. Он хвата вредност аргумента током позива и омогућава проверу његових поља појединачно. ArgumentCaptor је посебно користан када тестирани код ствара објекат унутар себе и прослеђује га зависности — не можете овај објекат проверити другачије.

java
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());

Анотације @Mock и @InjectMocks

@Mock и @InjectMocks — две кључне анотације Mockito-а које значајно смањују boilerplate код. @Mock креира мок за поље, а @InjectMocks убризгава све мокове из тестне класе у тестирани објекат кроз конструктор, сетер или поље.

Механизам @InjectMocks покушава да убризга зависности следећим редоследом: конструктор са највећим бројем аргумената, сетер по типу, приватно поље. Ако ниједан начин не успе — објекат остаје са null зависностима и тест пада са NullPointerException.

Правила коришћења @InjectMocks

Важно је разумети: @InjectMocks не анализира типове поља — подмеће било који мок компатибилан по типу. Ако у класи постоје два поља истог типа — Mockito може убризгати погрешан мок. У таквим случајевима препоручује се коришћење експлицитног конструктора са прослеђивањем мокова.

Mockito у Android пројектима

У Android развоју, Mockito се користи заједно са JUnit за тестирање ViewModel, Repository и UseCase. Пошто ове класе раде на JVM без Android контекста, Mockito замењује њихове зависности — Room DAO, Retrofit API, SharedPreferences — стабовима са предвидљивим понашањем.

Подешавање Gradle за Mockito

За додавање Mockito у Android пројекат, довољно је додати зависност mockito-core или mockito-inline (ова друга подржава моковање final класа и статичких метода). Верзија 5.12.0 (2024) укључује подршку за Java 21 и побољшану интеграцију са JUnit 5.

kotlin
// build.gradle.kts (модул)
dependencies {
    testImplementation("org.mockito:mockito-core:5.12.0")
    testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}

Mockito и PowerMock: застарела пракса

Раније је за моковање статичких метода и конструктора био потребан PowerMock — проширење које ради кроз бајткод-инструментацију. Почев од Mockito 5.x са mockito-inline, ова могућност је уграђена директно: mockStatic(ClassName.class) омогућава моковање статичких метода без додатних библиотека.

Тестирање ViewModel са Mockito

Типичан сценарио: ViewModel позива метод репозиторијума и трансформише резултат у UI стање. Mockito замењује репозиторијум, а тест проверава да ViewModel коректно обрађује успешан одговор и грешку. Код архитектуре Clean Architecture, мокови се креирају за сваки слој: DataSource, Repository и UseCase — ово омогућава тестирање сваког слоја изоловано.

  • success case — when(repo.getData()).thenReturn(Result.success(data)) → проверавамо state = Success(data).
  • error case — when(repo.getData()).thenReturn(Result.error(exception)) → проверавамо state = Error(message).
  • loading state — verify да је ViewModel поставила isLoading = true пре позива репозиторијума.

Често постављана питања

По чему се Mockito разликује од MockK?

Mockito — библиотека за Java и Kotlin која користи прокси и рефлексију. MockK — Kotlin-first библиотека са подршком за корутине, extension функције и final класе без додатне конфигурације.

Како креирати мок за final класу у Mockito?

Од Mockito 2.1, моковање final класа је подржано кроз opt-in. У верзији 5.x (mockito-inline) ово је укључено подразумевано. Довољно је додати зависност mockito-inline и користити стандардни mock() метод.

Шта је Spy у Mockito?

Spy — делимични мок који подразумевано позива стварне методе, али омогућава преправљање неких од њих кроз when().thenReturn(). Spy је користан за тестирање legacy кода када се не може преписати цела класа.

Која је разлика између thenReturn и thenAnswer?

thenReturn увек враћа исту вредност, без обзира на аргументе. thenAnswer израчунава повратну вредност на основу позива — аргумената, самог мока, стања. За динамичке одговоре увек користите thenAnswer.

Зашто је verify важан за тестове са моковима?

Verify проверава не само резултат, већ и процес — чињеницу обраћања зависности. Ово је критично за сервисе који морају да сачувају податке или пошаљу обавештења. Без verify, тест неће открити да метод није позвао save() или send().

Закључци

  • Mockito — библиотека за креирање мок-објеката, стандард de facto за моковање у Java и Kotlin.
  • Мокови се креирају кроз mock(Class) или анотацију @Mock са MockitoExtension.
  • Stubbing кроз when().thenReturn() задаје понашање метода мока.
  • Verify проверава чињеницу и број позива метода мока са наведеним аргументима.
  • @InjectMocks аутоматски убризгава мокове у тестирани објекат.
  • Android интеграција — Mockito се користи за тестирање ViewModel, Repository и UseCase.
  • ArgumentCaptor хвата аргументе позива за детаљну проверу поља објекта.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође