Java Mock Testing Framework Mockito

Java 常用类库Java Common Class Libraries


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:

  1. External dependencies may be unstable or unavailable
  2. Test execution speed becomes slower
  3. 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:

  1. Concise API: Gentle learning curve, easy to get started
  2. Powerful functionality: Supports method call verification, return value configuration, exception throwing, etc.
  3. Good readability: Test code is intuitive and easy to understand
  4. Active community: Continuously updated and maintained, with comprehensive documentation

Mockito Core Concepts

1. Creating Mock Objects

Example

// Method 1: Use static method
List mockedList = Mockito.mock(List.class);

// Method 2: Use annotations (requires MockitoJUnitRunner)
@Mock
List mockedList;

2. Setting Method Behavior

Example

// Return 100 when mockedList.size() is called
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 that mockedList.add("one") was called once
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

public class UserService {
    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

public class UserServiceTest {
    @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

// Any integer argument
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 inOrder = inOrder(mockedList);

inOrder.verify(mockedList).add("first");
inOrder.verify(mockedList).add("second");

3. Partial Mock (Spy)

Example

List realList = new ArrayList();
List spyList = spy(realList);

// Call real method
spyList.add("real");

// Mock a specific method
doReturn(100).when(spyList).size();

Best Practices

  1. Don't overuse Mock: Only mock necessary dependencies, keep tests realistic
  2. Verify interactions in moderation: Focus on important interactions, don't verify every method call
  3. Keep tests concise: Each test method should test only one functional point
  4. Organize test code reasonably: Use @Before for common setup
  5. 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.


Related Links

  1. Mockito Official Documentation
  2. Mockito GitHub Repository

Java 常用类库Java Common Class Libraries

Other Extensions