Andrei Pall

Linux Software Engineering

Mockito Examples

Mockito is a Java mocking framework used in unit testing to create fake objects, simulate method responses, and verify interactions between objects.

It is commonly used with JUnit 5 to test Java classes without connecting to real databases, APIs, Solr servers, or other external services.

Below are practical examples, starting with basic mocking and progressing to more advanced scenarios.

1. Add Mockito to your Java project

For a Maven project, add the following dependencies to your pom.xml:

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.13.4</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.20.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>5.20.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

These are example versions; use compatible versions approved for your project.

2. Basic example: Mock an object

Suppose you have this interface:

public interface UserRepository {
    String findUsernameById(int id);
}

You can mock it without implementing the interface.

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class UserRepositoryTest {

    @Test
    void testMockObject() {

        // Create mock
        UserRepository repository = mock(UserRepository.class);

        // Define mock behavior
        when(repository.findUsernameById(1))
            .thenReturn("Andrei");

        // Call mocked method
        String username = repository.findUsernameById(1);

        // Verify result
        assertEquals("Andrei", username);

        // Verify method was called
        verify(repository).findUsernameById(1);
    }
}

Explanation:

  • mock() creates a mock object.
  • when() defines the expected behavior.
  • thenReturn() specifies the value returned.
  • verify() checks whether a method was called.
  • assertEquals() checks the returned result.

The real UserRepository implementation is never executed.

3. Mock a dependency using @Mock and @InjectMocks

This is one of the most common ways to use Mockito.

Suppose you have a service that depends on a repository.

UserRepository.java

public interface UserRepository {
    String findUsernameById(int id);
}

UserService.java

public class UserService {

    private final UserRepository repository;

    public UserService(UserRepository repository) {
        this.repository = repository;
    }

    public String getUsername(int id) {
        return repository.findUsernameById(id);
    }
}

Now test the service without using a real repository.

UserServiceTest.java

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository repository;

    @InjectMocks
    private UserService service;

    @Test
    void testGetUsername() {

        when(repository.findUsernameById(10))
            .thenReturn("Andrei");

        String result = service.getUsername(10);

        assertEquals("Andrei", result);

        verify(repository, times(1))
            .findUsernameById(10);
    }
}

Important annotations:

Annotation Purpose
@Mock Creates a mock object
@InjectMocks Creates the tested object and injects mocks into it
@Spy Creates a partial mock that calls real methods by default
@Captor Captures arguments passed to mocked methods
@ExtendWith(MockitoExtension.class) Initializes Mockito annotations for JUnit 5

@InjectMocks supports constructor, setter, and field injection. Constructor injection is generally preferable.

4. Mock methods with different arguments

You can configure different responses depending on the input.

UserRepository repository = mock(UserRepository.class);

when(repository.findUsernameById(1))
    .thenReturn("Andrei");

when(repository.findUsernameById(2))
    .thenReturn("John");

when(repository.findUsernameById(3))
    .thenReturn("Maria");

System.out.println(repository.findUsernameById(1));
// Andrei

System.out.println(repository.findUsernameById(2));
// John

System.out.println(repository.findUsernameById(3));
// Maria

You can also use argument matchers:

when(repository.findUsernameById(anyInt()))
    .thenReturn("Unknown");

Or:

when(repository.findUsernameById(intThat(id -> id > 100)))
    .thenReturn("External user");

Other useful matchers include anyString(), eq(), isNull(), and argThat().

5. Mock exceptions

Mockito can simulate failures without actually causing external services to fail.

For example:

UserRepository repository = mock(UserRepository.class);

when(repository.findUsernameById(99))
    .thenThrow(new RuntimeException("Database unavailable"));

assertThrows(RuntimeException.class, () -> {
    repository.findUsernameById(99);
});

This is useful for testing exception handling, database connection failures, API timeouts, and Solr errors.

6. Mock void methods

Suppose you have:

public interface NotificationService {
    void sendEmail(String email, String message);
}

Because sendEmail() returns void, you use doThrow() rather than when().thenThrow().

NotificationService notification =
    mock(NotificationService.class);

// Simulate an exception
doThrow(new RuntimeException("SMTP error"))
    .when(notification)
    .sendEmail(anyString(), anyString());

assertThrows(RuntimeException.class, () -> {
    notification.sendEmail(
        "test@example.com",
        "Hello"
    );
});

For normal behavior, void methods on mocks do nothing by default.

You can simply verify them:

NotificationService notification =
    mock(NotificationService.class);

notification.sendEmail("test@example.com", "Hello");

verify(notification).sendEmail(
    "test@example.com",
    "Hello"
);

7. Verify method calls

Mockito can check whether methods were called and how many times.

UserRepository repository = mock(UserRepository.class);

repository.findUsernameById(1);
repository.findUsernameById(1);
repository.findUsernameById(2);

// Called exactly twice
verify(repository, times(2))
    .findUsernameById(1);

// Called exactly once
verify(repository, times(1))
    .findUsernameById(2);

// Never called
verify(repository, never())
    .findUsernameById(3);

// Called at least once
verify(repository, atLeastOnce())
    .findUsernameById(1);

// Called at most three times
verify(repository, atMost(3))
    .findUsernameById(1);

To verify that no methods were called:

verifyNoInteractions(repository);

To verify that no additional interactions occurred:

verifyNoMoreInteractions(repository);

8. Mock consecutive method responses

Sometimes you need the same method to return different values on successive calls.

UserRepository repository = mock(UserRepository.class);

when(repository.findUsernameById(1))
    .thenReturn("First")
    .thenReturn("Second")
    .thenReturn("Third");

System.out.println(repository.findUsernameById(1));
// First

System.out.println(repository.findUsernameById(1));
// Second

System.out.println(repository.findUsernameById(1));
// Third

System.out.println(repository.findUsernameById(1));
// Third

This is useful for testing retry logic, polling, and status changes.

9. Mock real classes instead of interfaces

Mockito can mock concrete Java classes as well.

Suppose you have:

public class DatabaseConnection {

    public boolean connect() {
        // Real database connection
        return true;
    }

    public String getStatus() {
        return "Connected";
    }
}

Test:

@Test
void testDatabaseMock() {

    DatabaseConnection db =
        mock(DatabaseConnection.class);

    when(db.connect()).thenReturn(false);

    when(db.getStatus())
        .thenReturn("Connection failed");

    assertFalse(db.connect());

    assertEquals(
        "Connection failed",
        db.getStatus()
    );
}

The real methods are not executed.

10. Partial mocking with @Spy

A spy wraps a real object and allows you to override selected methods.

import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.List;

@Test
void testSpy() {

    List<String> list = spy(new ArrayList<>());

    // Real method is executed
    list.add("Java");
    list.add("Mockito");

    // Override size()
    doReturn(100).when(list).size();

    System.out.println(list.get(0));
    // Java

    System.out.println(list.size());
    // 100

    verify(list).add("Java");
}

Difference between Mock and Spy:

Behavior Mock Spy
Calls real methods by default No Yes
Can override methods Yes Yes
Uses real object state No Yes
Typical purpose Isolate dependencies Partial mocking

With spies, prefer:

doReturn(100).when(list).size();

instead of:

when(list.size()).thenReturn(100);

because the second form calls the real method during stubbing.

11. Capture method arguments using ArgumentCaptor

Suppose you want to verify the actual message passed to a notification service.

import org.mockito.ArgumentCaptor;

@Test
void testArgumentCaptor() {

    NotificationService notification =
        mock(NotificationService.class);

    notification.sendEmail(
        "admin@example.com",
        "Archive completed"
    );

    ArgumentCaptor<String> captor =
        ArgumentCaptor.forClass(String.class);

    verify(notification).sendEmail(
        eq("admin@example.com"),
        captor.capture()
    );

    assertEquals(
        "Archive completed",
        captor.getValue()
    );
}

This is especially useful when the tested class generates values internally.

12. Practical example: Mock an Apache Solr client

Since Mockito can mock external service clients, here is an example using Apache SolrJ.

Suppose your application uses SolrClient to query a Solr server.

SolrSearchService.java

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;

public class SolrSearchService {

    private final SolrClient solrClient;

    public SolrSearchService(SolrClient solrClient) {
        this.solrClient = solrClient;
    }

    public long getNumberOfResults(String query)
            throws Exception {

        SolrQuery solrQuery = new SolrQuery(query);

        QueryResponse response =
            solrClient.query(solrQuery);

        SolrDocumentList results =
            response.getResults();

        return results.getNumFound();
    }
}

Now test it without connecting to a real Solr server.

SolrSearchServiceTest.java

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;

@ExtendWith(MockitoExtension.class)
class SolrSearchServiceTest {

    @Mock
    private SolrClient solrClient;

    @Mock
    private QueryResponse queryResponse;

    @InjectMocks
    private SolrSearchService searchService;

    @Test
    void testGetNumberOfResults() throws Exception {

        SolrDocumentList documents =
            new SolrDocumentList();

        documents.setNumFound(150);

        when(solrClient.query(any(SolrQuery.class)))
            .thenReturn(queryResponse);

        when(queryResponse.getResults())
            .thenReturn(documents);

        long count =
            searchService.getNumberOfResults("title:archive");

        assertEquals(150, count);

        verify(solrClient, times(1))
            .query(argThat(query ->
                "title:archive".equals(query.getQuery())
            ));
    }
}

In this test:

  • No real Solr server is required.
  • No HTTP requests are made.
  • The mocked Solr response reports 150 matching documents.
  • The test verifies that the expected Solr query was submitted.

This approach works with Http2SolrClient, database repositories, REST API clients, and other dependencies.

13. Mock static methods

Modern Mockito supports mocking static methods.

Suppose you have:

public class Utils {

    public static String getServerName() {
        return "production-server";
    }
}

Test:

import org.mockito.MockedStatic;

@Test
void testStaticMock() {

    try (MockedStatic<Utils> mocked =
            mockStatic(Utils.class)) {

        mocked.when(Utils::getServerName)
            .thenReturn("test-server");

        assertEquals(
            "test-server",
            Utils.getServerName()
        );

        mocked.verify(Utils::getServerName);
    }
}

The static mock is automatically closed after the try block, restoring normal behavior.

14. Mock object construction

Mockito can also intercept calls to new for supported classes.

import org.mockito.MockedConstruction;

@Test
void testConstructorMock() {

    try (MockedConstruction<DatabaseConnection> mocked =
            mockConstruction(
                DatabaseConnection.class,
                (mock, context) -> {
                    when(mock.connect()).thenReturn(true);
                }
            )) {

        DatabaseConnection db =
            new DatabaseConnection();

        assertTrue(db.connect());

        assertEquals(1, mocked.constructed().size());
    }
}

This can help when testing legacy code that creates dependencies internally. For new code, constructor dependency injection is usually a better design.


15. Mockito quick reference

Task Mockito code
Create mock mock(MyClass.class)
Return value when(mock.method()).thenReturn(value)
Throw exception when(mock.method()).thenThrow(exception)
Mock void exception doThrow(exception).when(mock).method()
Verify call verify(mock).method()
Verify twice verify(mock, times(2)).method()
Verify never called verify(mock, never()).method()
Match any string anyString()
Match exact argument eq(value)
Capture argument ArgumentCaptor.forClass(String.class)
Create spy spy(realObject)
Mock static method mockStatic(MyClass.class)
Mock constructor mockConstruction(MyClass.class)
Reset mock reset(mock)

For most Java projects, I recommend using JUnit 5 + Mockito with @Mock, @InjectMocks, and MockitoExtension.

The important principle is to mock the dependencies, not the class you are testing. For example, when testing a class that communicates with Apache Solr, create a real instance of your service and mock only its SolrClient dependency.

This gives you fast, isolated unit tests that don’t require running MySQL, Solr, Docker, or external HTTP services.

Newer >>