Introduction
In this chapter, we will learn about mocking static methods using Mockito. Static methods are often used in utility classes and are not tied to a specific instance of a class. Mocking static methods allows you to isolate your tests from the actual static method implementations, making your tests more robust and easier to maintain.
What is Mocking Static Methods?
Mocking static methods involves creating a mock for methods that belong to a class rather than an instance of a class. This is useful for isolating tests from static methods that have side effects, such as those that interact with external systems or perform complex calculations.
Setting Up Mockito to Mock Static Methods
To mock static methods with Mockito, you need to use the mockito-inline
library, which provides the necessary functionality. Ensure that you have the following dependencies in your pom.xml
if you are using Maven:
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 dependency -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
Example 1: DateUtils Class and BookingService Class
Utility Class with Static Methods
import java.time.LocalDate;
public class DateUtils {
public static boolean isWeekend(LocalDate date) {
return date.getDayOfWeek().getValue() >= 6;
}
public static LocalDate getCurrentDate() {
return LocalDate.now();
}
}
Service Class Using Static Methods
import java.time.LocalDate;
public class BookingService {
public boolean isBookingAllowed() {
LocalDate today = DateUtils.getCurrentDate();
return !DateUtils.isWeekend(today);
}
}
Test Class: BookingServiceTest
import static org.mockito.Mockito.*;
import static org.mockito.ArgumentMatchers.*;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.junit.jupiter.api.Assertions.*;
import java.time.LocalDate;
public class BookingServiceTest {
@Test
void testIsBookingAllowed_MockStaticMethods() {
try (MockedStatic<DateUtils> mockedStatic = mockStatic(DateUtils.class)) {
// Mock the static method getCurrentDate to return a specific date
mockedStatic.when(DateUtils::getCurrentDate).thenReturn(LocalDate.of(2023, 1, 1));
// Mock the static method isWeekend to return true for the specific date
mockedStatic.when(() -> DateUtils.isWeekend(LocalDate.of(2023, 1, 1))).thenReturn(true);
// Create an instance of BookingService
BookingService bookingService = new BookingService();
// Call the method under test
boolean result = bookingService.isBookingAllowed();
// Assert the result
assertFalse(result);
// Verify that the static methods were called
mockedStatic.verify(DateUtils::getCurrentDate);
mockedStatic.verify(() -> DateUtils.isWeekend(LocalDate.of(2023, 1, 1)));
}
}
}
Explanation
- Creating Mocks:
try (MockedStatic<DateUtils> mockedStatic = mockStatic(DateUtils.class)) {
This line creates a mock object for the
DateUtils
class using a try-with-resources statement to ensure the mock is closed after use. - Mocking Static Methods:
mockedStatic.when(DateUtils::getCurrentDate).thenReturn(LocalDate.of(2023, 1, 1)); mockedStatic.when(() -> DateUtils.isWeekend(LocalDate.of(2023, 1, 1))).thenReturn(true);
These lines mock the
getCurrentDate
andisWeekend
static methods to returnJanuary 1, 2023
andtrue
respectively, regardless of the input arguments. - Creating an Instance of BookingService:
BookingService bookingService = new BookingService();
This line creates an instance of the
BookingService
class. - Calling the Method Under Test:
boolean result = bookingService.isBookingAllowed();
This line calls the
isBookingAllowed
method on theBookingService
instance. - Asserting the Result:
assertFalse(result);
This line asserts that the returned value is
false
. - Verifying the Static Methods Were Called:
mockedStatic.verify(DateUtils::getCurrentDate); mockedStatic.verify(() -> DateUtils.isWeekend(LocalDate.of(2023, 1, 1)));
These lines verify that the
getCurrentDate
andisWeekend
static methods were called with the specified arguments.
Output
Example 2: StringUtils Class and TextService Class
Utility Class with Static Methods
public class StringUtils {
public static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
public static String reverse(String str) {
return new StringBuilder(str).reverse().toString();
}
}
Service Class Using Static Methods
public class TextService {
public String processText(String input) {
if (StringUtils.isNullOrEmpty(input)) {
return "Invalid input";
}
return StringUtils.reverse(input);
}
}
Test Class: TextServiceTest
import static org.mockito.Mockito.*;
import static org.mockito.ArgumentMatchers.*;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.junit.jupiter.api.Assertions.*;
public class TextServiceTest {
@Test
void testProcessText_MockStaticMethods() {
try (MockedStatic<StringUtils> mockedStatic = mockStatic(StringUtils.class)) {
// Mock the static method isNullOrEmpty to return true for empty string
mockedStatic.when(() -> StringUtils.isNullOrEmpty(anyString())).thenReturn(true);
// Mock the static method reverse to return the reversed string
mockedStatic.when(() -> StringUtils.reverse(anyString())).thenAnswer(invocation -> {
String str = invocation.getArgument(0);
return new StringBuilder(str).reverse().toString();
});
// Create an instance of TextService
TextService textService = new TextService();
// Call the method under test with an empty string
String result = textService.processText("");
// Assert the result
assertEquals("Invalid input", result);
// Call the method under test with a non-empty string
String result2 = textService.processText("hello");
// Assert the result
assertEquals("olleh", result2);
// Verify that the static methods were called
mockedStatic.verify(() -> StringUtils.isNullOrEmpty(""));
mockedStatic.verify(() -> StringUtils.reverse("hello"));
}
}
}
Explanation
- Creating Mocks:
try (MockedStatic<StringUtils> mockedStatic = mockStatic(StringUtils.class)) {
This line creates a mock object for the
StringUtils
class using a try-with-resources statement to ensure the mock is closed after use. - Mocking Static Methods:
mockedStatic.when(() -> StringUtils.isNullOrEmpty(anyString())).thenReturn(true); mockedStatic.when(() -> StringUtils.reverse(anyString())).thenAnswer(invocation -> { String str = invocation.getArgument(0); return new StringBuilder(str).reverse().toString(); });
These lines mock the
isNullOrEmpty
andreverse
static methods to returntrue
for any string and the reversed string respectively, regardless of the input arguments. - Creating an Instance of TextService:
TextService textService = new TextService();
This line creates an instance of the
TextService
class. - Calling the Method Under Test with an Empty String:
String result = textService.processText("");
This line calls the
processText
method on theTextService
instance with an empty string. - Asserting the Result for Empty String:
assertEquals("Invalid input", result);
This line asserts that the returned value is
Invalid input
. - Calling the Method Under Test with a Non-Empty String:
String result2 = textService.processText("hello");
This line calls the
processText
method on theTextService
instance with the string “hello”. - Asserting the Result for Non-Empty String:
assertEquals("olleh", result2);
This line asserts that the returned value is the reversed string “olleh”.
- Verifying the Static Methods Were Called:
mockedStatic.verify(() -> StringUtils.isNullOrEmpty("")); mockedStatic.verify(() -> StringUtils.reverse("hello"));
These lines verify that the
isNullOrEmpty
andreverse
static methods were called with the specified arguments.
Conclusion
Mocking static methods using Mockito allows you to isolate your tests from the actual implementations of static methods.
By using the mockito-inline
library, you can mock static methods and verify their interactions, making your tests more robust and maintainable. Understanding and utilizing static method mocking will help you write more effective and isolated unit tests. In this chapter, we covered two real-world examples: mocking static date utility methods and mocking static string utility methods. These examples demonstrate how to use Mockito to mock static methods and verify their behavior in different scenarios.