Mocking static methods in Java can be achieved using PowerMock, which extends the capabilities of Mockito. Here's a detailed example of how to mock a static method using both PowerMock and Mockito:
Using PowerMock with EasyMock
First, let's consider an example where we have a class `IdGenerator` with a static method `generateNewId()` that we want to mock. This method is used by another class, `ServiceRegistrator`.
java
public class IdGenerator {
public static long generateNewId() {
return System.currentTimeMillis();
}
}
public class ServiceRegistrator {
public long registerService(Object service) {
final long id = IdGenerator.generateNewId();
// Other logic...
return id;
}
}
To mock the static method `generateNewId()`, you would use PowerMock's `mockStatic` method along with EasyMock. Here's how you can write a test for it:
java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(IdGenerator.class)
public class ServiceRegistratorTest {
@Test
public void testRegisterService() throws Exception {
long expectedId = 42;
// Mock the static method
PowerMock.mockStatic(IdGenerator.class);
PowerMock.expect(IdGenerator.generateNewId()).andReturn(expectedId);
PowerMock.replay(IdGenerator.class);
// Create an instance of the class under test
ServiceRegistrator tested = new ServiceRegistrator();
// Call the method that uses the static method
long actualId = tested.registerService(new Object());
// Verify the static method was called
PowerMock.verify(IdGenerator.class);
// Assert the result
assertEquals(expectedId, actualId);
// Clean up
PowerMock.resetAll();
}
}
Using PowerMock with Mockito
Now, let's see how to achieve the same using Mockito with PowerMock. This approach is similar but uses Mockito's syntax for stubbing expectations.
Assume we have a class `StaticUtil` with a static method `firstStaticMethod()` that we want to mock.
java
public class StaticUtil {
public static String firstStaticMethod(String param) {
return "Original Result";
}
}
Here's how you can mock this method using PowerMock with Mockito:
java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(StaticUtil.class)
public class StaticUtilTest {
@Test
public void testMethodThatCallsStaticMethod() {
// Mock all static methods in the class
PowerMockito.mockStatic(StaticUtil.class);
// Set up the expectation for the static method
String param = "testParam";
String expectedValue = "Mocked Result";
Mockito.when(StaticUtil.firstStaticMethod(param)).thenReturn(expectedValue);
// Call the method that uses the static method
String actualValue = StaticUtil.firstStaticMethod(param);
// Verify the static method was called
PowerMockito.verifyStatic(StaticUtil.class);
StaticUtil.firstStaticMethod(param);
// Assert the result
assertEquals(expectedValue, actualValue);
}
}
Key Points
- Annotations: Use `@RunWith(PowerMockRunner.class)` to enable PowerMock and `@PrepareForTest` to specify the class containing the static method you want to mock.
- Mocking Static Methods: Use `PowerMock.mockStatic()` with EasyMock or `PowerMockito.mockStatic()` with Mockito to enable mocking of static methods.
- Setting Expectations: Use `PowerMock.expect()` with EasyMock or `Mockito.when()` with Mockito to set up return values for the static methods.
- Verification: Use `PowerMock.verify()` with EasyMock or `PowerMockito.verifyStatic()` with Mockito to verify that the static methods were called as expected.
Conclusion
PowerMock provides powerful capabilities to mock static methods, which can be challenging with standard Mockito. By combining PowerMock with either EasyMock or Mockito, you can effectively test code that uses static methods. However, it's worth noting that Mockito itself now supports mocking static methods using the `mockStatic` method from the `mockito-inline` library, but this requires a different setup and is not covered in this example.
Citations:[1] https://github.com/powermock/powermock/wiki/mockstatic
[2] https://github.com/powermock/powermock/wiki/mockito
[3] https://github.com/powermock/powermock/wiki/Mockito/cebcc5324cd3991cacdf5e1319209e5c4cd80fd3
[4] https://stackoverflow.com/questions/64607243/mocking-a-static-method-using-powermockito
[5] https://stackoverflow.com/questions/10583202/powermockito-mock-single-static-method-and-return-object
[6] https://www.baeldung.com/mockito-mock-static-methods
[7] https://blog.knoldus.com/mocking-static-methods-with-powermock/
[8] https://www.reddit.com/r/javahelp/comments/1g9f3a2/not_able_to_mock_a_static_method_in_beam_pipeline/
[9] https://www.testim.io/blog/mocking-static-methods-mockito/