Skip to main content

On This Page

Why Mocking Java Collections with Mockito is Problematic

2 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

Why We Should Not Mock Collections With Mockito

Mockito, a popular testing library in the Java ecosystem, is often misused by mocking Java collections such as List, Set, or Map, which can lead to brittle tests and unrealistic behavior. According to Neetika Khandelwal, mocking collections is rarely a good idea and can result in test failures on modern Java versions due to stricter JVM constraints.

Why This Matters

Mocking collections can increase complexity without providing meaningful isolation, as Java collections are part of the core JDK, deterministic, lightweight, and extensively tested. This practice can lead to tests that pass even though they do not reflect real runtime behavior, ultimately reducing confidence in the tests. For instance, on Java 21 and later, Mockito may throw an exception when attempting to mock a List, highlighting the potential issues with this approach.

Key Insights

  • Mockito cannot mock certain core JDK types, such as List, on newer Java versions: Java 21 and later have stricter JVM rules around runtime instrumentation of core JDK types.
  • Using real collections in tests tends to expose design issues and encourages cleaner APIs: by avoiding mocking collections, developers can write more resilient and maintainable code.
  • Good unit tests should protect refactoring, not resist it: tests should focus on observable behavior rather than implementation details.

Working Example

public class UserService {
    private final List<String> users;
    public UserService(List<String> users) {
        this.users = users;
    }
    public boolean hasUsers() {
        return !users.isEmpty();
    }
    public String getFirstUser() {
        if (users.isEmpty()) {
            return null;
        }
        return users.get(0);
    }
}
@Test
void givenList_whenRealCollectionIsUsed_thenShouldReturnFirstUser() {
    List<String> users = new ArrayList<>();
    users.add("Joey");
    UserService userService = new UserService(users);
    assertTrue(userService.hasUsers());
    assertEquals("Joey", userService.getFirstUser());
}

Practical Applications

  • Use Case: Using real collections in tests, such as ArrayList, to verify the behavior of a UserService class.
  • Pitfall: Mocking collections with Mockito, which can lead to brittle tests and unrealistic behavior, and potentially cause test failures on newer Java versions.

References:

Continue reading

Next article

Clearing Console Screen in Java

Related Content