PowerMock and Mockito are used to mock static methods in Java

Mockito enables the creation of mock objects. As static methods are associated with the class, Mockito does not offer the capability to mock them. Nevertheless, it is possible to utilize the PowerMock framework in conjunction with Mockito to mock static methods.

Use PowerMock to create a Mockito mock for a static method.

PowerMock offers various modules to enhance the capabilities of the Mockito framework and execute JUnit and TestNG test cases. It should be noted that PowerMock does not currently support JUnit 5, hence we will be creating JUnit 4 test cases. Furthermore, we will comprehend the integration of TestNG with Mockito and PowerMock.

Dependencies required for PowerMock

For mocking static methods in Mockito, we require the PowerMock dependencies mentioned below.

  • powermock-api-mockito2: This is the core PowerMock dependency and used to extend Mockito2 mocking framework. If you are using Mockito 1.x versions then use powermock-api-mockito module.
  • powermock-module-junit4: For running JUnit 4 test cases using PowerMock.
  • powermock-module-testng: For running TestNG test cases and supporting PowerMock.

Here is the last pom.xml file of our project.

<project xmlns="https://maven.apache.org/POM/4.0.0"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.scdev.powermock</groupId>
	<artifactId>PowerMock-Examples</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<testng.version>6.14.3</testng.version>
		<junit4.version>4.12</junit4.version>
		<mockito-core.version>2.19.0</mockito-core.version>
		<powermock.version>2.0.0-beta.5</powermock.version>
		<java.version>10</java.version>
	</properties>

	<dependencies>
		<!-- TestNG -->
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>${testng.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- JUnit 4 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit4.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- Mockito 2 -->
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>${mockito-core.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- PowerMock TestNG Module -->
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-module-testng</artifactId>
			<version>${powermock.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- PowerMock JUnit 4.4+ Module -->
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-module-junit4</artifactId>
			<version>${powermock.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- PowerMock Mockito2 API -->
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito2</artifactId>
			<version>${powermock.version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.7.0</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.22.0</version>
				<dependencies>
					<dependency>
						<groupId>org.apache.maven.surefire</groupId>
						<artifactId>surefire-junit47</artifactId>
						<version>2.22.0</version>
					</dependency>
					<dependency>
						<groupId>org.apache.maven.surefire</groupId>
						<artifactId>surefire-testng</artifactId>
						<version>2.22.0</version>
					</dependency>
				</dependencies>
				<configuration>
					<additionalClasspathElements>
						<additionalClasspathElement>src/test/java/</additionalClasspathElement>
					</additionalClasspathElements>
					<!-- TestNG Test Fails when executed from command line with message
						"Cannot use a threadCount parameter less than 1" 
						Works when threadCount is explicitly specified 
						https://gist.github.com/juherr/6eb3e93e2db33979b7e90b63ddadc888-->
					<threadCount>5</threadCount>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Please note that I am currently using the PowerMock version 2.0.0-beta.5. This particular version is compatible with Java 10, although it is still in the beta stage, meaning there may be some problems in more complicated scenarios. When I attempted to use the stable version 1.7.x, I encountered the following error messages.

java.lang.NoSuchMethodError: org.mockito.internal.handler.MockHandlerFactory.createMockHandler(Lorg/mockito/mock/MockCreationSettings;)Lorg/mockito/internal/InternalMockHandler;
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:114)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:69)
	at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
	at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:73)

These are the GitHub issues that have been opened for this exception – issue1 and issue2. We can proceed by creating a basic class with a static method.

package com.scdev.mockito.staticmethod;

public class Utils {

	public static boolean print(String msg) {
		System.out.println("Printing "+msg);
		return true;
	}
}

Example of JUnit Mockito PowerMock

To incorporate PowerMock into Mockito and JUnit 4, we must follow these steps.

  • Annotate test class with @RunWith(PowerMockRunner.class) annotation.
  • Annotate test class with @PrepareForTest and provide classed to be mocked using PowerMock.
  • Use PowerMockito.mockStatic() for mocking class with static methods.
  • Use PowerMockito.verifyStatic() for verifying mocked methods using Mockito.

I will provide you with one option for paraphrasing the given statement natively:

“This JUnit test case demonstrates a comprehensive instance of mocking a static method using Mockito and PowerMock.”

package com.scdev.mockito.staticmethod;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class JUnit4PowerMockitoStaticTest{

	@Test
	public void test_static_mock_methods() {
		PowerMockito.mockStatic(Utils.class);
		when(Utils.print("Hello")).thenReturn(true);
		when(Utils.print("Wrong Message")).thenReturn(false);
		
		assertTrue(Utils.print("Hello"));
		assertFalse(Utils.print("Wrong Message"));
		
		PowerMockito.verifyStatic(Utils.class, atLeast(2));
		Utils.print(anyString());
	}
}

Example of using TestNG, Mockito, and PowerMock.

@RunWith annotation is not necessary for TestNG test cases. Instead, we should extend PowerMockTestCase in our test classes in order to create test class instances using PowerMockObjectFactory.

package com.scdev.mockito.staticmethod;

import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

import static org.mockito.Mockito.*;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.annotations.Test;

@PrepareForTest(Utils.class)
public class TestNGPowerMockitoStaticTest extends PowerMockTestCase{

	@Test
	public void test_static_mock_methods() {
		PowerMockito.mockStatic(Utils.class);
		when(Utils.print("Hello")).thenReturn(true);
		when(Utils.print("Wrong Message")).thenReturn(false);
		
		assertTrue(Utils.print("Hello"));
		assertFalse(Utils.print("Wrong Message"));
		
		PowerMockito.verifyStatic(Utils.class);
		Utils.print("Hello");
		PowerMockito.verifyStatic(Utils.class, times(2));
		Utils.print(anyString());
	}
}

Summarize the given information using your own words, providing only one option.

PowerMock offers additional capabilities for testing static methods in Mockito. It seamlessly works with JUnit 4 and TestNG, but there are currently no plans to provide support for JUnit 5 in the near future.

You have the option to download the entire project from our GitHub Repository.

Leave a Reply 0

Your email address will not be published. Required fields are marked *