PowerMock API extension for EasyMock providing advanced mocking capabilities for static methods, constructors, final classes, and private methods through bytecode manipulation.
—
PowerMock enables testing of private method behavior through expectation setup and verification. This capability is essential for testing internal class logic, method interactions, and complex private method workflows without exposing implementation details through public APIs.
Set up expectations for private method calls using method names and arguments.
/**
* Used to specify expectations on private methods using the method name.
*
* @param instance the object instance containing the private method
* @param methodName the name of the private method
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be found or invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName, Object... arguments) throws Exception;
/**
* Used to specify expectations on private methods without specifying a method name.
* PowerMock tries to find a unique method based on argument parameters.
*
* @param instance the object instance containing the private method
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be found or invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, Object... arguments) throws Exception;import org.powermock.api.easymock.PowerMock;
import org.powermock.reflect.Whitebox;
public class PrivateMethodTest {
@Test
public void testPrivateMethodExpectation() throws Exception {
UserService userService = PowerMock.createPartialMock(UserService.class, "validateUser");
// Set up expectation for private method call
PowerMock.expectPrivate(userService, "validateUser", "john.doe")
.andReturn(true);
PowerMock.replay(userService);
// Call public method that internally calls private validateUser method
boolean result = userService.authenticateUser("john.doe", "password123");
assertTrue(result);
PowerMock.verify(userService);
}
@Test
public void testPrivateMethodWithoutName() throws Exception {
Calculator calculator = PowerMock.createPartialMock(Calculator.class, "computeInternal");
// PowerMock finds method based on argument types
PowerMock.expectPrivate(calculator, 5, 3) // Finds method with (int, int) signature
.andReturn(8);
PowerMock.replay(calculator);
int result = calculator.add(5, 3); // Calls private computeInternal(5, 3)
assertEquals(8, result);
PowerMock.verify(calculator);
}
}Set up expectations using Method objects for precise method identification.
/**
* Used to specify expectations on private methods using Method objects.
*
* @param instance the object instance containing the private method
* @param method the Method object representing the private method
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, Method method, Object... arguments) throws Exception;
/**
* Used to specify expectations on private static methods using Method objects.
*
* @param clazz the class containing the private static method
* @param method the Method object representing the private static method
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Class<?> clazz, Method method, Object... arguments) throws Exception;@Test
public void testPrivateMethodWithMethodObject() throws Exception {
SecurityManager securityManager = PowerMock.createPartialMock(SecurityManager.class, "checkPermissions");
// Get the private method using reflection
Method checkPermissionsMethod = Whitebox.getMethod(SecurityManager.class, "checkPermissions", String.class, User.class);
User testUser = new User("testuser");
PowerMock.expectPrivate(securityManager, checkPermissionsMethod, "read", testUser)
.andReturn(true);
PowerMock.replay(securityManager);
boolean hasAccess = securityManager.hasReadAccess("read", testUser);
assertTrue(hasAccess);
PowerMock.verify(securityManager);
}Handle overloaded private methods by specifying parameter types explicitly.
/**
* Used to specify expectations on overloaded private methods.
*
* @param instance the object instance containing the private method
* @param methodName the name of the private method
* @param parameterTypes the parameter types to distinguish overloaded methods
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be found or invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
Class<?>[] parameterTypes, Object... arguments) throws Exception;@Test
public void testOverloadedPrivateMethods() throws Exception {
DataProcessor processor = PowerMock.createPartialMock(DataProcessor.class, "processData");
// Handle overloaded private methods by specifying parameter types
Class<?>[] stringArrayType = {String[].class};
Class<?>[] listType = {List.class};
String[] stringData = {"a", "b", "c"};
List<String> listData = Arrays.asList("x", "y", "z");
// Set up expectations for different overloaded methods
PowerMock.expectPrivate(processor, "processData", stringArrayType, new Object[]{stringData})
.andReturn("array-processed");
PowerMock.expectPrivate(processor, "processData", listType, listData)
.andReturn("list-processed");
PowerMock.replay(processor);
String result1 = processor.handleArrayData(stringData); // Calls processData(String[])
String result2 = processor.handleListData(listData); // Calls processData(List)
assertEquals("array-processed", result1);
assertEquals("list-processed", result2);
PowerMock.verify(processor);
}Specify private method expectations at specific levels in the class hierarchy.
/**
* Used to specify expectations for private methods at a specific place in the class hierarchy.
*
* @param instance the object instance containing the private method
* @param methodName the name of the private method
* @param where the class in the hierarchy where the method is defined
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be found or invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
Class<?> where, Object... arguments) throws Exception;
/**
* Used to specify expectations for overloaded private methods at a specific place in the class hierarchy.
*
* @param instance the object instance containing the private method
* @param methodName the name of the private method
* @param where the class in the hierarchy where the method is defined
* @param parameterTypes the parameter types to distinguish overloaded methods
* @param arguments the method arguments
* @return expectation setter for further configuration
* @throws Exception if method cannot be found or invoked
*/
public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
Class<?> where, Class<?>[] parameterTypes, Object... arguments) throws Exception;class BaseService {
private String formatMessage(String msg) {
return "Base: " + msg;
}
}
class ExtendedService extends BaseService {
private String formatMessage(String msg) {
return "Extended: " + msg;
}
public String processMessage(String msg) {
// Calls private method - but which one?
return formatMessage(msg);
}
}
@Test
public void testPrivateMethodInHierarchy() throws Exception {
ExtendedService service = PowerMock.createPartialMock(ExtendedService.class, "formatMessage");
// Specify which class's private method to mock
PowerMock.expectPrivate(service, "formatMessage", BaseService.class, "test")
.andReturn("Mocked base message");
PowerMock.expectPrivate(service, "formatMessage", ExtendedService.class, "test")
.andReturn("Mocked extended message");
PowerMock.replay(service);
String result = service.processMessage("test");
assertEquals("Mocked extended message", result); // Uses ExtendedService's method
PowerMock.verify(service);
}Verify that private methods are called with expected parameters and frequencies.
@Test
public void testPrivateMethodSideEffects() throws Exception {
AuditLogger logger = PowerMock.createPartialMock(AuditLogger.class, "writeToFile");
// Expect private method to be called twice with different parameters
PowerMock.expectPrivate(logger, "writeToFile", "login", "user1").once();
PowerMock.expectPrivate(logger, "writeToFile", "logout", "user1").once();
PowerMock.replay(logger);
// Public methods that internally call private writeToFile method
logger.logUserLogin("user1");
logger.logUserLogout("user1");
PowerMock.verify(logger); // Verifies both private method calls occurred
}Set up private method expectations to throw exceptions.
@Test(expected = ProcessingException.class)
public void testPrivateMethodThrowsException() throws Exception {
FileManager fileManager = PowerMock.createPartialMock(FileManager.class, "validatePath");
PowerMock.expectPrivate(fileManager, "validatePath", "/invalid/path")
.andThrow(new ProcessingException("Invalid path"));
PowerMock.replay(fileManager);
fileManager.openFile("/invalid/path"); // Calls private validatePath method
// Test expects ProcessingException to be thrown
}Combine private method expectations with direct private method invocation testing.
@Test
public void testPrivateMethodDirectly() throws Exception {
CryptoService cryptoService = new CryptoService();
// Test private method directly using Whitebox
String result = Whitebox.invokeMethod(cryptoService, "generateSalt", 16);
assertNotNull(result);
assertEquals(16, result.length());
// Also test through partial mocking
CryptoService mockCrypto = PowerMock.createPartialMock(CryptoService.class, "generateSalt");
PowerMock.expectPrivate(mockCrypto, "generateSalt", 16).andReturn("fixed-salt-value");
PowerMock.replay(mockCrypto);
String encryptedData = mockCrypto.encryptData("secret"); // Uses mocked generateSalt
assertTrue(encryptedData.contains("fixed-salt-value"));
PowerMock.verify(mockCrypto);
}To set up expectations for private methods, you must create a partial mock that includes the private method names:
// Correct: Include private method in partial mock
MyService service = PowerMock.createPartialMock(MyService.class, "privateMethod");
// Incorrect: Full mock doesn't allow private method expectations
MyService service = PowerMock.createMock(MyService.class); // Won't work for private methodsPowerMock can access private methods from any visibility level:
private - Standard private methodsprotected - Protected methods accessible in subclassesPrivate static methods are handled similarly but use the class instead of instance:
PowerMock.expectPrivate(MyUtilClass.class, "privateStaticMethod", "param")
.andReturn("result");Install with Tessl CLI
npx tessl i tessl/maven-org-powermock--powermock-api-easymock