Mockito — what it is, key concepts and how it works

Author: IT Sectr Published: 2026-04-08 Reading time: 8 min

Mockito is an open-source framework for creating mock objects in Java and Kotlin unit tests, which allows isolating the tested code from external dependencies. With its help, a developer replaces real repositories, API clients, and databases with controlled stubs that have predefined behavior. According to Mockito.org, the library is used in more than 60% of Java projects that use unit testing.

Key Takeaways

  • Mockito — a library for creating mock objects that replace real dependencies in tests.
  • Mock — a stub object that simulates the behavior of a real component.
  • Stubbing — configuring the return value when calling a mock method.
  • Verify — checking that a method was called with specific arguments.
  • @InjectMocks — automatic injection of mock dependencies into the tested object.

What is Mockito?

Mockito is an open-source library for creating mock objects (stubs) in unit tests for Java, Kotlin, and other JVM languages. Unlike JUnit, which handles test execution, Mockito solves the isolation problem — it replaces real dependencies of the tested class with predictable objects.

Without mocks, testing a method that accesses a database or external API requires setting up a real environment — deploying a database, starting a server. Mockito replaces these dependencies with objects that have fixed behavior: the repository.findById(1) method always returns a given User object without accessing the database.

Mockito’s architecture is based on the Proxy pattern (for interfaces and classes). The library generates a subclass or proxy for the specified type and intercepts all method calls, returning default values or values set via when().thenReturn().

How Mockito Works

The principle of Mockito’s operation is built on three basic operations: creating a mock, configuring behavior (stubbing), and verifying calls (verification). Each operation uses static methods from the org.mockito.Mockito class — the most downloaded class in the Java ecosystem according to Maven Central statistics. All mock method calls are recorded in memory, allowing later verification through verify.

Three steps of a test with Mockito

A typical test with Mockito consists of three phases: Arrange — creating mocks and configuring stubs via when().thenReturn(), Act — calling the tested method, Assert — checking the result via assertEquals and verify(mock). This approach is called AAA (Arrange-Act-Assert).

Basic example with a repository mock

Let’s look at a simple test where Mockito replaces a user repository. The when().thenReturn() method configures the mock so that the findById call returns a pre-prepared User object.

java
// Creating a repository mock
UserRepository mockRepo = mock(UserRepository.class);

// Configuring behavior: findById(1) returns a user
when(mockRepo.findById(1)).thenReturn(new User("Alice"));

// Checking that the method was actually called
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);

Creating Mock Objects

Mockito provides two ways to create mocks: the static mock(Class) method and the @Mock annotation with initialization via MockitoAnnotations.openMocks(). The first approach is compact for one or two mocks, the second is convenient when there are many dependencies — annotations reduce boilerplate code.

Via the static mock() method

The mock() method takes a class and returns a stub object that can be configured via when().thenReturn(). All unconfigured methods return default values: 0 for numbers, false for boolean, null for objects.

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

Via the @Mock annotation with JUnit 5

The @Mock annotation combined with @ExtendWith(MockitoExtension.class) automatically creates mocks for all fields of the test class. The MockitoExtension is responsible for initialization before each test.

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: Configuring Mock Behavior

Stubbing is the process of defining what a mock method should return when called with specific arguments. The basic syntax: when(mock.method(args)).thenReturn(value). For different scenarios, Mockito offers several then-method variants.

MethodPurpose
thenReturn(value)Always returns the specified value
thenThrow(exception)Throws an exception when called
thenAnswer(answer)Calculates the return value dynamically
thenCallRealMethod()Calls the real method (partial mock)

Dynamic response via thenAnswer

When the return value depends on the call arguments, thenAnswer is used with a lambda. This is useful for simulating work with real data — for example, generating an ID based on the passed object.

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

Verify: Checking Mock Interactions

Verify is a unique feature of Mockito that older mock object libraries (EasyMock, jMock) do not provide.

Verify makes tests more reliable because it checks not only the return value but also side effects — calls to methods that don’t return a result (void methods). The verify(mock).methodName(args) method checks whether a specific mock method was called with the specified arguments. This allows testing not only the result but also the process — the fact of accessing the dependency.

Checking the number of calls

By default, verify checks that the method was called exactly once. If a different count is needed, times(n), atLeast(n), never(), and other modifiers from the Mockito class are used.

java
// Checking the number of calls
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);

// Checking the order of calls
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();

ArgumentCaptor for capturing arguments

When you need to check exactly which object a method was called with, ArgumentCaptor is used. It captures the argument value during the call and allows checking its fields individually. ArgumentCaptor is especially useful when the tested code creates an object internally and passes it to a dependency — you cannot check that object otherwise.

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

@Mock and @InjectMocks Annotations

@Mock and @InjectMocks are two key Mockito annotations that significantly reduce boilerplate code. @Mock creates a mock for a field, and @InjectMocks injects all mocks from the test class into the tested object via constructor, setter, or field.

The @InjectMocks mechanism attempts to inject dependencies in the following order: constructor with the most arguments, setter by type, private field. If none of these methods work, the object remains with null dependencies, and the test will fail with a NullPointerException.

Rules for using @InjectMocks

It’s important to understand: @InjectMocks does not analyze field types — it substitutes any mock that is compatible by type. If a class has two fields of the same type, Mockito may inject the wrong mock. In such cases, it is recommended to use an explicit constructor with mock parameters.

Mockito in Android Projects

In Android development, Mockito is used together with JUnit for testing ViewModel, Repository, and UseCase. Since these classes run on the JVM without the Android context, Mockito replaces their dependencies — Room DAO, Retrofit API, SharedPreferences — with stubs that have predictable behavior.

Gradle setup for Mockito

To add Mockito to an Android project, simply add the mockito-core or mockito-inline dependency (the latter supports mocking final classes and static methods). Version 5.12.0 (2024) includes Java 21 support and improved JUnit 5 integration.

kotlin
// build.gradle.kts (module)
dependencies {
    testImplementation("org.mockito:mockito-core:5.12.0")
    testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}

Mockito and PowerMock: outdated practice

Previously, mocking static methods and constructors required PowerMock — an extension that worked through bytecode instrumentation. Starting with Mockito 5.x with mockito-inline, this capability is built-in directly: mockStatic(ClassName.class) allows mocking static methods without additional libraries.

Testing ViewModel with Mockito

A typical scenario: a ViewModel calls a repository method and transforms the result into UI state. Mockito replaces the repository, and the test checks that the ViewModel correctly handles both the success response and the error. When using the Clean Architecture, mocks are created for each layer: DataSource, Repository, and UseCase — this allows testing each layer in isolation.

  • success case — when(repo.getData()).thenReturn(Result.success(data)) → check state = Success(data).
  • error case — when(repo.getData()).thenReturn(Result.error(exception)) → check state = Error(message).
  • loading state — verify that the ViewModel set isLoading = true before calling the repository.

Frequently Asked Questions

How is Mockito different from MockK?

Mockito is a library for Java and Kotlin that uses proxies and reflection. MockK is a Kotlin-first library with support for coroutines, extension functions, and final classes without additional configuration.

How to create a mock for a final class in Mockito?

Starting with Mockito 2.1, mocking final classes is supported via opt-in. In version 5.x (mockito-inline), this is enabled by default. Simply add the mockito-inline dependency and use the standard mock() method.

What is a Spy in Mockito?

A Spy is a partial mock that by default calls real methods but allows overriding some of them via when().thenReturn(). Spy is useful for testing legacy code when you cannot rewrite the entire class.

What’s the difference between thenReturn and thenAnswer?

thenReturn always returns the same value regardless of arguments. thenAnswer calculates the return value based on the invocation — call arguments, the mock itself, and state. For dynamic responses, always use thenAnswer.

Why is verify important for tests with mocks?

Verify checks not only the result but also the process — the fact of accessing the dependency. This is critical for services that need to save data or send notifications. Without verify, the test will not detect that a method didn’t call save() or send().

Summary

  • Mockito — a library for creating mock objects, the de facto standard for mocking in Java and Kotlin.
  • Mocks are created via mock(Class) or the @Mock annotation with MockitoExtension.
  • Stubbing via when().thenReturn() defines mock method behavior.
  • Verify checks the fact and number of mock method calls with specified arguments.
  • @InjectMocks automatically injects mocks into the tested object.
  • Android integration — Mockito is used for testing ViewModel, Repository, and UseCase.
  • ArgumentCaptor captures call arguments for detailed object field checking.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also