Table of Contents
1. Overview
Mockito is a powerful, open-source Mocking framework in Java. The features it provides for unit-testing is inevitably unique and important, nonetheless, ease out a lot of work for developers while writing unit test cases.
While Mockito can help with virtually everything, there are some things it cannot do. Like stubbing or testing private, final or static methods. It needs much more power to write test cases for such methods which usually causes developers to write cumbersome code for these methods.
Here, PowerMockito comes to the rescue. PowerMockito is capable of testing private, final or static methods as it makes use of Java Reflection API. Let’s see the demonstration in action while we study its uses.
2. Create a simple java maven project.
3. Adding Dependencies with Maven
As we have talked earlier, the best way to get started with Mockito, or PowerMockito is to find its Maven dependency and add it to our project. Here are the dependencies we need to add:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.4</version> <scope>test</scope> </dependency> |
Now that we are done adding dependencies, let’s enable the use of annotations in our tests.
Your pom.xml will look like below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.arpit.java2blog</groupId> <artifactId>PowerMockitoExample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.4</version> <scope>test</scope> </dependency> </dependencies> </project> |
4. Enabling PowerMock Annotations
Just like what we need to do with Mockito, we also need to enable the use of Annotations with PowerMockito. Much like Mockito, we make use of similar annotations, as shown:
1 2 3 4 5 6 7 8 9 10 11 12 |
import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(fullyQualifiedNames = "org.arpit.java2blog.*") public class PowerTest { ... } |
Let us look at each annotation we used above:
- @RunWith annotation is similar to what we did in Mockito. Instead of using Mockito, we will use a PowerMockRunner this time, which will enablePowerMockito APIs in the test.
- @PrepareForTest was provided a fullyQualifiedNames package with a wildcard. This informs PowerMockito which classes to prepare with Java Reflection API for testing.
5. Mocking final methods
Let’s start working with PowerMockito API by mocking final methods. To mock final methods, not much to the surprise, we should first define final methods. Here is an example of the model we will be testing:
1 2 3 4 5 6 7 8 9 10 |
package org.arpit.java2blog.model; public class ClassWithFinalMethods { public final String printMessage(String message) { return message; } } |
Simple enough, the method just returns the String which is passed to it. Now, it’s time to write our test:
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 |
package org.arpit.java2blog.powermock; import org.arpit.java2blog.model.ClassWithFinalMethods; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(fullyQualifiedNames = "org.arpit.java2blog.*") public class PowerMockFinalMethodTest { @Test public void testClassWithFinalMethods_printMessage_finalMethod() throws Exception { String message = "Hello PowerMockito"; //1 ClassWithFinalMethods mockObject = PowerMockito.mock(ClassWithFinalMethods.class); //2 PowerMockito.whenNew(ClassWithFinalMethods.class).withNoArguments().thenReturn(mockObject); //3 ClassWithFinalMethods object = new ClassWithFinalMethods(); //4 PowerMockito.verifyNew(ClassWithFinalMethods.class).withNoArguments(); //5 PowerMockito.when(object.printMessage(message)).thenReturn(message); //6 String helloPowerMockito = object.printMessage(message); //7 Mockito.verify(object).printMessage(message); //8 Assert.assertEquals(message, helloPowerMockito); //9 } } |
We have used class names while using methods so that no confusion arises when importing the classes. Let us explain the whole lot which happened in above test:
- We defined a generic String message which we will be using as a parameter and expectation.
- We mock an instance of the system under test, ClassWithFinalMethods.
- whenNew() method makes sure that whenever an instance of this class is made using the new keyword by invoking a no argument constructor, this mock instance is returned instead of the real object.
- We invoke the no argument constructor to make an instance of the system under test.
- We verify that the no argument constructor was actually involved during the last step.
- We set an expected String when the final method is called, using the String we defined in Step 1.
- The final method printMessage(…) is invoked.
- We verify that the final method was actually called.
- Finally, we assert our expectations to the actual String returned to us.
Now that was a lot actually. We used a simple example so that everything makes sense. As we have explicitly used class names with static methods, this test is ready to be run.
6. Mocking static methods
We are through final methods now. It’s time to learn how static methods can be tested withPowerMockito. We make a new class named as ClassWithStaticMethod and add new methods, which are static in nature:
1 2 3 4 5 6 7 8 9 10 |
package org.arpit.java2blog.model; public class ClassWithStaticMethod { public static String printMessage(String message) { return message; } } |
A similar method as earlier, the method just returns the String which is passed to it. Now, it’s time to write our test:
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 |
package org.arpit.java2blog.powermock; import org.arpit.java2blog.model.ClassWithStaticMethod; import org.junit.Assert; 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(fullyQualifiedNames = "org.arpit.java2blog.*") public class PowerMockStaticMethodTest { @Test public void testClassWithStaticMethod_printMessage_staticMethod() { String message = "Hello PowerMockito"; //1 String expectation = "Expectation"; //2 PowerMockito.mockStatic(ClassWithStaticMethod.class); //3 PowerMockito.when(ClassWithStaticMethod.printMessage(message)).thenReturn(expectation); //4 String actual = ClassWithStaticMethod.printMessage(message); //5 Assert.assertEquals(expectation, actual); //6 } } |
This test was smaller than earlier. Let us talk about each step we performed here:
- We defined a generic String message which we will be using as a parameter.
- Another generic String message, to be used as an expectation.
- Prepare ClassWithStaticMethod for static method test.
- Preparing expectations when the static method will be invoked.
- Invoking the static method.
- Verifying the expected and actual result.
Testing static method is quite simple actually. the key part is to call PowerMockito.mockStatic(…) so that PowerMockito API is enabled for the class.
7. Mocking private methods
Down to the last bit, in this section, we will test private methods. This is another awesome usage of Reflection API in Java. First, we define our system under test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package org.arpit.java2blog.model; public class ClassWithPrivateMethods { private String printMessage(String message) { return message; } public String privateCall(String message) { return printMessage(message); } } |
Now, defining a public message which internally calls the private message is necessary. Let us see our test to see how it makes use of reflection API:
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 |
package org.arpit.java2blog.powermock; import org.arpit.java2blog.model.ClassWithPrivateMethods; import org.junit.Assert; 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(fullyQualifiedNames = "org.arpit.java2blog.*") public class PowerMockPrivateMethodTest { @Test public void testClassWithPrivateMethods_printMessage_privateMethod() throws Exception { String message = "Hello PowerMockito"; String expectation = "Expectation"; ClassWithPrivateMethods mock = PowerMockito.spy(new ClassWithPrivateMethods()); PowerMockito.doReturn(expectation).when(mock, "printMessage", message); String actual = mock.privateCall(message); Assert.assertEquals(expectation, actual); } } |
Here, few things to point out are:
- We start by creating a mock using Powermockito.spy(…) method.
- Next, we make use of Reflection API by providing method name as a String parameter to when(…) method.
- Finally, we invoke the public method which in turn invoked the private method and we verify our results using assertEquals(…) method.
8. Conclusion
In this lesson, we studied simple yet concise examples on how we can make use of PowerMockito API to stub and test private, final or static methods. This was a missing feature in Mockito, which was completed by PowerMockito API.
This is the best of all the explanations out there. Crisp and to the point. Thanks!