Mockito
Unit Testing Tool
Mockito
Overview
Mockito is the most popular mocking framework for Java used for Test-Driven Development (TDD) and Behavior-Driven Development (BDD). It enables the creation of test double objects (mock objects) in automated unit tests to validate interactions between objects. Mockito lets you write beautiful tests with a clean and simple API, making it a truly "tasty" mocking framework.
Details
Mockito was originally developed to address shortcomings of existing mocking frameworks like EasyMock and JMock. Today, it's used in over 30,000 GitHub projects and has been voted by the massive StackOverflow community as the best mocking framework for Java. The latest version as of 2024 is 5.14.2, requiring Java 11 or higher.
Key features of Mockito:
- Simple API: Intuitive and easy-to-remember API design
- Powerful verification: Detailed verification of method call counts, order, and arguments
- Flexible stubbing: Freedom to set method return values and exceptions
- Argument matchers: Flexible argument matching for verification
- Spy functionality: Partial mocking of real objects
- Static method mocking: Mock static method calls (using mockito-inline)
- Constructor mocking: Mock class instantiation
Mockito 5 switches the default mockmaker to mockito-inline and requires Java 11. This enables mocking of final classes and methods by default.
Advantages and Disadvantages
Advantages
- Low learning curve: Intuitive API that's easy for beginners to master
- Rich documentation: Comprehensive official documentation and examples
- Excellent integration: Seamless integration with JUnit, TestNG, and Spring Boot
- Detailed error messages: Clear error information when tests fail
- High performance: Lightweight and fast test execution
- Active community: Large user community and continuous development
- BDD support: Behavior-driven development style support through BDDMockito
Disadvantages
- Over-mocking risk: Over-reliance on mocks may miss actual integration issues
- Java language only: Cannot be used with other programming languages
- Learning curve: Advanced features (custom answers, argument captors) require time to master
- Debugging difficulty: Complex mock setups can be hard to debug
- Implementation coupling: Mocks may become tightly coupled to implementation details
Reference Pages
Usage Examples
Basic Setup
Maven Dependencies
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.14.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.14.2</version>
<scope>test</scope>
</dependency>
JUnit 5 Integration
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Test
void shouldCreateUser() {
// Test implementation
}
}
Mock Creation and Stubbing
Basic Mock Creation
// Create mock
List<String> mockedList = mock(List.class);
// Stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.size()).thenReturn(5);
// Usage
System.out.println(mockedList.get(0)); // "first"
System.out.println(mockedList.size()); // 5
Exception Stubbing
when(mockedList.get(anyInt())).thenThrow(new RuntimeException());
// void method exception
doThrow(new RuntimeException()).when(mockedList).clear();
Verification
Basic Verification
// Verify method calls
verify(mockedList).add("item");
verify(mockedList, times(1)).clear();
verify(mockedList, never()).remove("item");
verify(mockedList, atLeastOnce()).size();
verify(mockedList, atMost(3)).get(anyInt());
Order Verification
InOrder inOrder = inOrder(mockedList);
inOrder.verify(mockedList).add("first");
inOrder.verify(mockedList).add("second");
Argument Matchers
Built-in Matchers
// Any argument
when(mockedList.get(anyInt())).thenReturn("element");
// Specific type
when(userService.findUser(any(String.class))).thenReturn(user);
// Argument captor
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mockedList).add(argument.capture());
assertEquals("captured value", argument.getValue());
Custom Matchers
when(userService.authenticate(argThat(user ->
user.getEmail().endsWith("@company.com")
))).thenReturn(true);
Spy (Partial Mocks)
Partial Mocking
List<String> list = new ArrayList<>();
List<String> spyList = spy(list);
// Real method is called
spyList.add("one");
spyList.add("two");
// Stubbing is also possible
when(spyList.size()).thenReturn(100);
assertEquals(100, spyList.size()); // Stubbed value
assertEquals("one", spyList.get(0)); // Real value
Custom Answers
Complex Behavior Definition
when(userService.processUser(any(User.class))).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
return "Processed: " + user.getName();
});
// Simple answer with lambda
when(calculator.add(anyInt(), anyInt())).thenAnswer(invocation -> {
int a = invocation.getArgument(0);
int b = invocation.getArgument(1);
return a + b;
});
BDD Style
Using BDDMockito
import static org.mockito.BDDMockito.*;
@Test
void shouldReturnUserWhenFound() {
// Given
User expectedUser = new User("John", "[email protected]");
given(userRepository.findById(1L)).willReturn(expectedUser);
// When
User actualUser = userService.getUser(1L);
// Then
then(userRepository).should().findById(1L);
assertThat(actualUser).isEqualTo(expectedUser);
}
Static Methods and Constructor Mocking
Static Method Mocking
@Test
void shouldMockStaticMethod() {
try (MockedStatic<LocalDateTime> mockedStatic = mockStatic(LocalDateTime.class)) {
LocalDateTime fixedTime = LocalDateTime.of(2024, 1, 1, 12, 0);
mockedStatic.when(LocalDateTime::now).thenReturn(fixedTime);
assertEquals(fixedTime, LocalDateTime.now());
}
}
Constructor Mocking
@Test
void shouldMockConstruction() {
try (MockedConstruction<File> mockedConstruction = mockConstruction(File.class)) {
File file = new File("test.txt");
verify(mockedConstruction.constructed().get(0)).exists();
}
}
Advanced Verification
Strict Stubbing
// Strict mode (detects unnecessary stubs)
MockitoSession mockito = Mockito.mockitoSession()
.initMocks(this)
.strictness(Strictness.STRICT_STUBS)
.startMocking();
// Change to lenient mode when needed
lenient().when(mockedList.get(0)).thenReturn("element");
Timeout Verification
// Verify calls within a time period
verify(mockedList, timeout(1000)).add("item");
verify(mockedList, timeout(1000).times(2)).clear();