Master PowerMock: Unit Test Private, Final, Static and Constructor Methods in Java
This guide explains why unit testing matters, compares Java testing tools, introduces PowerMock’s capabilities, details essential annotations, shows how to configure dependencies, and provides step‑by‑step code examples for mocking public, final, static, private, constructor, field and superclass methods.
Why Write Unit Tests
Unit tests reduce bug rates, improve code quality, and help developers become familiar with business logic. Many companies also enforce a minimum test‑coverage threshold before allowing a pull request to be merged.
Choosing a Unit Test Framework
In the Java ecosystem the most common stack is JUnit 4 together with a mocking library such as Mockito, JMock, EasyMock or PowerMock. PowerMock is chosen when the code under test depends on external services (e.g., email, network, SOA calls) that cannot be controlled, because it can mock static, final, private methods and constructors.
What Is PowerMock
PowerMock extends other mocking libraries (e.g., EasyMock) with a custom class loader and byte‑code manipulation to mock static methods, constructors, final classes/methods, private methods, and to suppress static initializers. It works without changing IDE or CI server settings and keeps the same API as the underlying mock framework.
Common Annotations
@RunWith(PowerMockRunner.class) – tells JUnit to use PowerMock’s runner.
@PrepareForTest({DemoDao.class}) – lists classes that need to be byte‑code manipulated (required for final, private, static, native methods).
@PowerMockIgnore({"javax.management.", "javax.net.ssl."}) – avoids class‑loader errors after using PowerMock.
@SuppressStaticInitializationFor – prevents static initializers from running; see the PowerMock wiki for more annotations.
Getting Started
JUnit 4.4+ Dependency Configuration
<properties>
<powermock.version>2.0.2</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>PowerMock Sample Code
The following classes illustrate a target class containing public, final, static, private and constructor‑throwing methods, which will be mocked in the test suite.
/**
* @Date 2020/3/31
* @Description
*/
@Repository
public class DemoDao {
public String mockPublicMethod(String type) throws Throwable {
throw new Throwable();
}
public final String mockFinalMethod(String type) throws Throwable {
throw new Throwable();
}
public static String mockStaticMethod(String type) throws Throwable {
throw new Throwable();
}
}
/**
* @Date 2020/3/31
* @Description
*/
@Component
public class DemoService extends AbstractDemo {
@Autowired
private DemoDao demoDao;
public String mockPublicMethod() throws Throwable {
return demoDao.mockPublicMethod("demo");
}
public String mockFinalMethod() throws Throwable {
return demoDao.mockFinalMethod("demo");
}
public String mockStaticMethod() throws Throwable {
return DemoDao.mockStaticMethod("demo");
}
private String callPrivateMethod(String type) {
return type;
}
public String mockPublicMethodCallPrivateMethod(String type) throws Throwable {
return callPrivateMethodThrowable(type);
}
private String callPrivateMethodThrowable(String type) throws Throwable {
throw new Throwable();
}
public String mockExtendMethod(String type) throws Throwable {
return getExtendMethod();
}
public static String UUID = "uuid";
}Mocking a Public Method
@RunWith(PowerMockRunner.class)
public class DemoServiceTest {
@InjectMocks
private DemoService demoService;
@Mock
private DemoDao demoDao;
@Test
public void mockPublicMethod() throws Throwable {
String type = UUID.randomUUID().toString();
PowerMockito.when(demoDao.mockPublicMethod(any())).thenReturn(type);
String result = demoService.mockPublicMethod();
Assert.assertEquals(type, result);
}
}Mocking a Final Method
@RunWith(PowerMockRunner.class)
@PrepareForTest(DemoDao.class)
public class DemoServiceTest {
@InjectMocks
private DemoService demoService;
@Mock
private DemoDao demoDao;
@Test
public void mockFinalMethod() throws Throwable {
String type = UUID.randomUUID().toString();
PowerMockito.when(demoDao.mockFinalMethod(any())).thenReturn(type);
String result = demoService.mockFinalMethod();
Assert.assertEquals(type, result);
}
}Mocking a Static Method
@RunWith(PowerMockRunner.class)
@PrepareForTest(DemoDao.class)
public class DemoServiceTest {
@InjectMocks
private DemoService demoService;
@Mock
private DemoDao demoDao;
@Test
public void mockStaticMethod() throws Throwable {
String type = UUID.randomUUID().toString();
PowerMockito.mockStatic(DemoDao.class);
PowerMockito.when(DemoDao.mockStaticMethod(any())).thenReturn(type);
String result = demoService.mockStaticMethod();
Assert.assertEquals(type, result);
}
}Invoking a Private Method
@Test
public void callPrivateMethod() throws Throwable {
String type = UUID.randomUUID().toString();
// First way
Method method = PowerMockito.method(DemoService.class, "callPrivateMethod", String.class);
String result = (String) method.invoke(demoService, type);
Assert.assertEquals(type, result);
// Second way
String result1 = Whitebox.invokeMethod(demoService, "callPrivateMethod", type);
Assert.assertEquals(type, result1);
}Mocking a Private Method
@Test
public void mockPrivateMethod() throws Throwable {
String type = UUID.randomUUID().toString();
demoService = PowerMockito.spy(demoService);
PowerMockito.doReturn(type).when(demoService, "callPrivateMethodThrowable", type);
String result = demoService.mockPublicMethodCallPrivateMethod(type);
Assert.assertEquals(type, result);
}Mocking a Superclass Method
@Test
public void mockExtendMethod() throws Throwable {
String type = UUID.randomUUID().toString();
Method method = PowerMockito.method(AbstractDemo.class, "getExtendMethod");
PowerMockito.replace(method).with((proxy, m, args) -> type);
String result = demoService.mockExtendMethod(type);
Assert.assertEquals(type, result);
}Mocking a Constructor
@Test
public void mockConstructorMethod() throws Throwable {
PowerMockito.whenNew(DemoService.class).withNoArguments().thenReturn(demoService);
}Mocking a Field
@Test
public void mockField() {
String uuid = UUID.randomUUID().toString();
Whitebox.setInternalState(DemoService.class, "UUID", uuid);
Assert.assertEquals(DemoService.UUID, uuid);
}Conclusion
The author acknowledges possible mistakes and invites readers to point them out. Feedback such as sharing, liking or commenting is appreciated.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
