Mockito allows us to create mock objects. Since static method belongs to the class, there is no way in Mockito to mock static methods. However, we can use PowerMock along with Mockito framework to mock static methods.
Mockito Mock Static Method using PowerMock
PowerMock provides different modules to extend Mockito framework and run JUnit and TestNG test cases.
Note that PowerMock doesn’t support JUnit 5 yet, so we will create JUnit 4 test cases. We will also learn how to integrate TestNG with Mockito and PowerMock.
PowerMock Dependencies
We need following PowerMock dependencies for mocking static methods in Mockito.
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 usepowermock-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.
Below is the final pom.xml from our project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
<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.journaldev.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> |
Note that I am using 2.0.0-beta.5
version of PowerMock. This version supports Java 10, however, it’s still in beta so there might be some issues present in complex cases.
When I tried to use current stable version 1.7.x
, I got the following errors.
1 2 3 4 5 6 7 |
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) |
Here are GitHub issues opened for this exception – issue1 and issue2.
Let’s create a simple class with a static method.
1 2 3 4 5 6 7 8 9 |
package com.journaldev.mockito.staticmethod; public class Utils { public static boolean print(String msg) { System.out.println("Printing "+msg); return true; } } |
JUnit Mockito PowerMock Example
We need to do the following to integrate PowerMock with Mockito and JUnit 4.
- 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.
Here is a complete example of mocking static method using Mockito and PowerMock in JUnit test case.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.journaldev.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()); } } |
TestNG Mockito PowerMock Example
For TestNG test cases, we don’t need to use @RunWith
annotation. We need test classes to extend PowerMockTestCase
so that PowerMockObjectFactory
is used to create test class instance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.journaldev.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()); } } |
Summary
PowerMock provides extended features for Mockito, one of them is the ability to test static methods. It’s easily integrated with JUnit 4 and TestNG. However, there is no near-term support plan for JUnit 5.