Java Mock Testing Framework Mockito
What is Mock Testing?
In software development, unit testing is an important means of verifying code functionality. However, when our code depends on external systems (such as databases, web services, etc.), testing directly can face several problems:
- External dependencies may be unstable or unavailable
- Test execution speed becomes slower
- It is difficult to simulate various boundary conditions
Mock testing (simulation testing) solves these problems by creating "stand-ins" for objects. Mock objects can:
- Simulate the behavior of real objects
- Verify whether interactions occur as expected
- Not execute the actual logic of real objects
Why Choose Mockito?
Mockito is currently the most popular Mock testing framework in the Java ecosystem, and it has the following advantages:
- Concise API: Gentle learning curve, easy to get started
- Powerful functionality: Supports method call verification, return value configuration, exception throwing, etc.
- Good readability: Test code is intuitive and easy to understand
- Active community: Continuously updated and maintained, with comprehensive documentation
Mockito Core Concepts
1. Creating Mock Objects
Example
List mockedList = Mockito.mock(List.class);
// Method 2: Use annotations (requires MockitoJUnitRunner)
@Mock
List mockedList;
2. Setting Method Behavior
Example
when(mockedList.size()).thenReturn(100);
// Return "first" when mockedList.get(0) is called
when(mockedList.get(0)).thenReturn("first");
// Throw an exception when mockedList.get(1) is called
when(mockedList.get(1)).thenThrow(new RuntimeException());
3. Verifying Interactions
Example
verify(mockedList).add("one");
// Verify that mockedList.clear() was never called
verify(mockedList, never()).clear();
// Verify that mockedList.add("two") was called at least twice
verify(mockedList, atLeast(2)).add("two");
Mockito Practical Application Examples
Testing User Service
Suppose we have aUserServicedepends onUserRepository:
Example
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found"));
}
}
Use Mockito for testing:
Example
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetUserById_Success() {
// Prepare test data
User mockUser = new User(1L, "testUser");
// Configure Mock behavior
when(userRepository.findById(1L))
.thenReturn(Optional.of(mockUser));
// Execute the test
User result = userService.getUserById(1L);
// Verify the result
assertEquals("testUser", result.getUsername());
verify(userRepository).findById(1L);
}
@Test(expected = UserNotFoundException.class)
public void testGetUserById_NotFound() {
when(userRepository.findById(2L))
.thenReturn(Optional.empty());
userService.getUserById(2L);
}
}
Mockito Advanced Features
1. Argument Matchers
Example
when(mockedList.get(anyInt())).thenReturn("element");
// Argument of a specific type
when(mockedList.contains(anyString())).thenReturn(true);
// Custom matcher
when(mockedList.add(argThat(arg -> arg.length() > 5))).thenReturn(true);
2. Verifying Call Order
Example
inOrder.verify(mockedList).add("first");
inOrder.verify(mockedList).add("second");
3. Partial Mock (Spy)
Example
List spyList = spy(realList);
// Call real method
spyList.add("real");
// Mock a specific method
doReturn(100).when(spyList).size();
Best Practices
- Don't overuse Mock: Only mock necessary dependencies, keep tests realistic
- Verify interactions in moderation: Focus on important interactions, don't verify every method call
- Keep tests concise: Each test method should test only one functional point
- Organize test code reasonably: Use @Before for common setup
- Combine with other testing tools: Use together with JUnit, AssertJ, etc.
Frequently Asked Questions (FAQ)
Q: What is the difference between Mockito and PowerMock?
A: Mockito is mainly used for mocking ordinary objects, while PowerMock can mock static methods, constructors, etc. However, PowerMock compromises test isolation, so it is recommended to use Mockito first.
Q: When should I use Spy instead of Mock?
A: Use Spy when you need mostly real behavior and only modify a few methods. If you need full control over object behavior, use Mock.
Q: Can Mockito be used for final classes or methods?
A: Since Mockito 2.1.0, final classes and methods can be mocked through configuration, but you need to addmockito-inlinedependency.
Java Common Class Libraries