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.

FunTester
FunTester
FunTester
Master PowerMock: Unit Test Private, Final, Static and Constructor Methods in Java

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaunit testingMockingJUnitPowerMockMockito
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.