PowerMock API extension for Mockito that enables mocking of static methods, constructors, final classes and methods, private methods, and advanced testing capabilities through bytecode manipulation and custom classloading
—
PowerMock provides enhanced stubbing capabilities that extend beyond standard Mockito when() syntax. These methods are essential for stubbing void methods, private methods, static methods, and scenarios where the standard approach cannot be used due to Java language limitations.
Stub methods with custom Answer implementations for complex return logic or side effects.
static PowerMockitoStubber doAnswer(Answer<?> answer);Parameters:
answer - Custom Answer implementation defining the method behaviorReturns: PowerMockitoStubber for chaining with method selection
Usage Example:
@Test
@PrepareForTest(DatabaseService.class)
public void testCustomAnswer() throws Exception {
DatabaseService service = spy(new DatabaseService());
doAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String query = (String) args[0];
return "Result for: " + query.toUpperCase();
}
}).when(service, "executeQuery", anyString());
String result = service.performSearch("select * from users");
assertEquals("Result for: SELECT * FROM USERS", result);
}Stub methods to throw specific exceptions, particularly useful for void methods and error scenario testing.
static PowerMockitoStubber doThrow(Throwable toBeThrown);Parameters:
toBeThrown - The exception to throw when the stubbed method is calledReturns: PowerMockitoStubber for chaining with method selection
Usage Example:
@Test
@PrepareForTest(FileManager.class)
public void testExceptionStubbing() throws Exception {
FileManager manager = spy(new FileManager());
// Stub private method to throw exception
doThrow(new IOException("Disk full")).when(manager, "writeToFile", anyString(), anyString());
// Test that exception is properly handled
assertThrows(FileOperationException.class, () -> {
manager.saveDocument("document.txt", "content");
});
}Stub methods to call their real implementation, useful for partial mocking scenarios.
static PowerMockitoStubber doCallRealMethod();Returns: PowerMockitoStubber for chaining with method selection
Usage Example:
@Test
@PrepareForTest(MathUtils.class)
public void testCallRealMethod() {
mockStatic(MathUtils.class);
// Mock one method but call real implementation for others
when(MathUtils.complexCalculation(anyDouble())).thenReturn(100.0);
doCallRealMethod().when(MathUtils.class);
MathUtils.simpleAddition(5, 3);
assertEquals(100.0, MathUtils.complexCalculation(50.0), 0.001);
assertEquals(8, MathUtils.simpleAddition(5, 3)); // Real implementation
}Stub void methods to do nothing, overriding default behavior or consecutive call stubbing.
static PowerMockitoStubber doNothing();Returns: PowerMockitoStubber for chaining with method selection
Usage Example:
@Test
@PrepareForTest(Logger.class)
public void testDoNothing() throws Exception {
Logger logger = spy(new Logger());
// Stub private void method to do nothing
doNothing().when(logger, "writeToFile", anyString());
// First call does nothing, second call throws exception
doNothing().doThrow(new IOException("File locked")).when(logger, "writeToFile", anyString());
logger.log("First message"); // Does nothing
assertThrows(IOException.class, () -> {
logger.log("Second message"); // Throws exception
});
}Stub methods to return specific values, particularly useful when when() syntax cannot be used.
static PowerMockitoStubber doReturn(Object toBeReturned);
static PowerMockitoStubber doReturn(Object toBeReturned, Object... othersToBeReturned);Parameters:
toBeReturned - The value to return when the stubbed method is calledothersToBeReturned - Additional values for consecutive callsReturns: PowerMockitoStubber for chaining with method selection
Usage Example:
@Test
@PrepareForTest(ConfigurationManager.class)
public void testDoReturn() throws Exception {
ConfigurationManager manager = spy(new ConfigurationManager());
// Use doReturn when when() would call the real method
doReturn("mocked-value").when(manager, "getConfigValue", "key");
// Multiple return values for consecutive calls
doReturn("first", "second", "third").when(manager, "getNextValue");
assertEquals("mocked-value", manager.getProperty("key"));
assertEquals("first", manager.getNext());
assertEquals("second", manager.getNext());
assertEquals("third", manager.getNext());
}The PowerMockitoStubber interface extends Mockito's Stubber with additional capabilities for static and private methods:
interface PowerMockitoStubber extends Stubber {
void when(Class<?> classMock);
<T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception;
<T> void when(T mock, Object... arguments) throws Exception;
<T> void when(T mock, String methodToExpected, Object... arguments) throws Exception;
<T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception;
<T> void when(Class<T> classMock, Object... arguments) throws Exception;
<T> void when(Class<T> classMock, String methodToExpected, Object... parameters) throws Exception;
}@Test
@PrepareForTest(SystemLogger.class)
public void testStaticVoidMethodStubbing() {
mockStatic(SystemLogger.class);
// Stub static void method to throw exception
doThrow(new RuntimeException("Logging failed")).when(SystemLogger.class);
SystemLogger.log(eq("ERROR"), anyString());
ServiceManager manager = new ServiceManager();
assertThrows(ServiceException.class, () -> {
manager.handleError("Critical error occurred");
});
}@Test
@PrepareForTest(NetworkService.class)
public void testConsecutiveBehavior() throws Exception {
NetworkService service = spy(new NetworkService());
// First call succeeds, second fails, third succeeds again
doReturn("success")
.doThrow(new NetworkException("Connection timeout"))
.doReturn("retry success")
.when(service, "attemptConnection", anyString());
assertEquals("success", service.connect("server1"));
assertThrows(NetworkException.class, () -> service.connect("server1"));
assertEquals("retry success", service.connect("server1"));
}@Test
@PrepareForTest(DataProcessor.class)
public void testComplexPrivateMethodStubbing() throws Exception {
DataProcessor processor = spy(new DataProcessor());
doAnswer(invocation -> {
String data = (String) invocation.getArguments()[0];
if (data.startsWith("PRIORITY")) {
return data.toUpperCase();
} else {
return data.toLowerCase();
}
}).when(processor, "transformData", anyString());
String priorityResult = processor.processData("PRIORITY: urgent message");
String normalResult = processor.processData("Normal message");
assertEquals("PRIORITY: URGENT MESSAGE", priorityResult);
assertEquals("normal message", normalResult);
}@Test
@PrepareForTest(CacheManager.class)
public void testSideEffects() throws Exception {
CacheManager manager = spy(new CacheManager());
AtomicInteger callCount = new AtomicInteger(0);
doAnswer(invocation -> {
callCount.incrementAndGet();
String key = (String) invocation.getArguments()[0];
return "cached-" + key + "-" + callCount.get();
}).when(manager, "getCachedValue", anyString());
String first = manager.getValue("key1");
String second = manager.getValue("key2");
assertEquals("cached-key1-1", first);
assertEquals("cached-key2-2", second);
assertEquals(2, callCount.get());
}@Test
@PrepareForTest(SecurityService.class)
public void testMixedStubbing() throws Exception {
SecurityService service = spy(new SecurityService());
// Use when() for return values
when(service.validateUser("admin")).thenReturn(true);
// Use doThrow for exceptions
doThrow(new SecurityException("Access denied")).when(service, "checkPermissions", "guest");
// Use doNothing for void methods
doNothing().when(service, "logSecurityEvent", anyString());
// Use doAnswer for complex logic
doAnswer(invocation -> {
String action = (String) invocation.getArguments()[0];
return "audit-" + action + "-" + System.currentTimeMillis();
}).when(service, "generateAuditId", anyString());
assertTrue(service.validateUser("admin"));
assertThrows(SecurityException.class, () -> service.authorize("guest", "read"));
String auditId = service.performAction("login");
assertTrue(auditId.startsWith("audit-login-"));
}@PrepareForTest annotation@RunWith(PowerMockRunner.class) or equivalentInstall with Tessl CLI
npx tessl i tessl/maven-org-powermock--powermock-api-mockito