PowerMockito Tutorial for Beginners
A unit test should test a class in isolation. Side effects from other classes or the system should be eliminated if possible. Mockito lets you write beautiful tests with a clean & simple API. In this example we will learn about PowerMockito which is an extension of Mockito. PowerMockito extends Mockito functionality with several new features such as mocking static and private methods and more. Tools and technologies used in this example are Java 1.8, Eclipse Luna 4.4.2
Table Of Contents
1. Introduction
Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability. Often testability corresponds to good design, but this is not always the case. For example final classes and methods cannot be used, private methods sometimes need to be protected or unnecessarily moved to a collaborator, static methods should be avoided completely and so on simply because of the limitations of existing frameworks.
Mockito is a popular mocking framework which can be used in conjunction with JUnit. Mockito allows us to create and configure mock objects. Using Mockito simplifies the development of tests for classes with external dependencies significantly. We can create the mock objects manually or can use the mocking framewors like Mockito, EasyMock. jMock etc. Mock frameworks allow us to create mock objects at runtime and define their behavior. The classical example for a mock object is a data provider. In production a real database is used, but for testing a mock object simulates the database and ensures that the test conditions are always the same.
PowerMock is a framework that extends other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more. By using a custom classloader no changes need to be done to the IDE or continuous integration servers which simplifies adoption. Developers familiar with the supported mock frameworks will find PowerMock easy to use, since the entire expectation API is the same, both for static methods and constructors. PowerMock aims to extend the existing API’s with a small number of methods and annotations to enable the extra features. Currently PowerMock supports EasyMock and Mockito.
When writing unit tests it is often useful to bypass encapsulation and therefore PowerMock includes several features that simplifies reflection specifically useful for testing. This allows easy access to internal state, but also simplifies partial and private mocking. PowerMock provides a class called PowerMockito
for creating mock/object/class and initiating verification, and expectations, everything else you can still use Mockito to setup and verify expectation (e.g. times()
, anyInt()
). All usages require@RunWith(PowerMockRunner.class)
and @PrepareForTest
annotated at class level.
2. Mocking
Mocking is a way to test the functionality of a class in isolation. Mock objects do the mocking of the real service. A mock object returns a dummy data corresponding to some dummy input passed to it.
To understand how PowerMockito works first we need to look at few of the terms which we use when using these frameworks.
A stub class is an partial implementation for an interface or class with the purpose of using an instance of this stub class during testing. Stubs usually do responding at all to anything outside what’s programmed in for the test. Stubs may also record information about calls.
A mock object is a dummy implementation for an interface or a class in which you define the output of certain method calls. You can create these mock objects manually (via code) or use a mock framework to simulate these classes. Mock frameworks allow you to create mock objects at runtime and define their behavior.
Below we define few differences between Mockito and PowerMock
- Mockito does not include specific language characteristics like constructors or static methods for mocking whereas PowerMock offers constructors and static methods to Mockito and other frameworks, through its individual classloader and bytecode management.
- Mockito does not require @RunWith annotation and base test class, while performing tests in suite whereas PowerMock requires both @RunWith annotation and a base test class for testing a suite.
- Mockito does not support mocking of constructors whereas PowerMock supports mocking of constructors and also supports mocking of (i) final (ii) static (iii) native and (iv) private methods.
PowerMock consists of two extension API’s. One for EasyMock and one for Mockito. To use PowerMock you need to depend on one of these API’s as well as a test framework. Currently PowerMock supports JUnit and TestNG. There are three different JUnit test executors available, one for JUnit 4.4+, one for JUnit 4.0-4.3 and one for JUnit 3. There’s one test executor for TestNG which requires version 5.11+ depending on which version of PowerMock you use.
3. Creating a project
Below are the steps we need to take to create the project.
- Open Eclipse. Go to File=>New=>Java Project. In the ‘Project name’ enter ‘PowerMockito’.
- Eclipse will create a ‘src’ folder. Right click on the ‘src’ folder and choose New=>Package. In the ‘Name’ text-box enter ‘com.javacodegeeks’. Click ‘Finish’.
3.1 Dependencies
For this example we need the below mentioned jars:
- cglib-nodep-3.2.2.jar
- easymock-3.4.jar
- hamcrest-all-1.3.jar
- javassist-3.12.1.GA.jar
- junit-4.12.jar
- objenesis-2.2.jar
- powermock-api-easymock-1.6.5.jar
- powermock-mockito-release-full-1.6.4-full.jar
These jars can be downloaded from Maven repository. These are the latest (non-beta) versions available as per now. To add these jars in the classpath right click on the project and choose Build Path=>Configure Build Path. The click on the ‘Add External JARs’ button on the right hand side. Then go to the location where you have downloaded these jars. Then click ok.
4. Simple Example
First we will see a simple example of using PowerMocito to mock methods. We will create a Controller and a service class. The controller class will have a reference to the service class which it will use to perform user actions.
4.1 Domain class
First we will see the User domain class. This class represents the User entity. (Please note that the actual User entity will have lot more fields but since here we are showing how to use PowerMock we are using a very simple User representation class.)
User.java
package com.javacodegeeks.user.domain; /** * Class representing User entity. * @author Meraj * */ public class User { private String firstName; private String surname; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } }
4.2 User Service
Now we will see how the User service class looks like. We will first create a class called DefaultUserService
which will implements the UserService
interface. Here we are interested in the getUserCount()
method which throws the UnsupportedOperationException
.
DefaultUserService.java
package com.javacodegeeks.user.service; import com.javacodegeeks.user.domain.User; /** * Default implementation of {@link UserService} * @author Meraj * */ public class DefaultUserService implements UserService { @Override public User getUserById(Long userId) { return null; } @Override public void updateUserDetails(User newUserDetails) { } @Override public void createUser(User user) { } @Override public Long getUserCount() { throw new UnsupportedOperationException("Not implemented"); } }
4.3 User Controller
This is the controller class for user related actions. It has the reference to the UserService class which gets sets when initiating the Controller class by calling it’s constructor.
public UserController(UserService userService) { this.userService = userService; }
UserController.java
package com.javacodegeeks.user.controller; import com.javacodegeeks.user.service.UserService; /** * Controller class handling the user operations * @author Meraj * */ public class UserController { private UserService userService; public UserController(UserService userService) { this.userService = userService; } public Long getUserCount() { return userService.getUserCount(); } }
4.4 User Controller Test
Now we will write the test class for this controller class and will see how we can mock the Service class. There are few things which needs some attention here. We will use the @RunWith
class annotation. This is defined in the junit library as shown below.
@Retention(value=RUNTIME) @Target(value=TYPE) @Inherited public @interface RunWith
When a class is annotated with @RunWith
or extends a class annotated with @RunWith
, JUnit will invoke the class it references to run the tests in that class instead of the runner built into JUnit.
We will use the org.powermock.modules.junit4.PowerMockRunner
class to run this tests. We will mock the DefaultUserService
class by calling the mock()
method of org.powermock.api.mockito.PowerMockito
.
PowerMockito.mock(DefaultUserService.class);
We will them pass this mock reference to the UserController
to set the service.
UserControllerTest.java
package com.javacodegeeks.user.test; import static org.junit.Assert.assertEquals; 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; import com.javacodegeeks.user.controller.UserController; import com.javacodegeeks.user.service.DefaultUserService; /** * Test class for UserController * @author Meraj * */ @RunWith(PowerMockRunner.class) @PrepareForTest(UserController.class) public class UserControllerTest { private DefaultUserService mockUserService; private UserController userController; @Test public void testGetUserCount() { mockUserService = PowerMockito.mock(DefaultUserService.class); PowerMockito.when(mockUserService.getUserCount()).thenReturn(100L); userController = new UserController(mockUserService); assertEquals(100L, userController.getUserCount().longValue()); } }
5. Mock static methods
We can use PowerMock to mock static methods. In this section we will see how we can mock a static method using PowerMock. We will use java.util.UUID
class for this. A UUID represents an immutable universally unique identifier (128 bit value). More details about this class can be found here: UUID Java Docs. In this class there is a method called randomUUID()
. It is used to retrieve a type 4 (pseudo randomly generated) UUID. The UUID is generated using a cryptographically strong pseudo random number generator.
We will create a simple method in the UserController
class to create random user id.
public String createUserId(User user) { return String.format("%s_%s", user.getSurname(), UUID.randomUUID().toString()); }
To tests this we will create a new test method in the UserControllerTest
class.
@Test public void testMockStatic() throws Exception { PowerMock.mockStaticPartial(UUID.class, "randomUUID"); EasyMock.expect(UUID.randomUUID()).andReturn(UUID.fromString("067e6162-3b6f-4ae2-a171-2470b63dff00")); PowerMock.replayAll(); UserController userController = new UserController(); Assert.assertTrue(userController.createUserId(getNewUser()).contains("067e6162-3b6f-4ae2-a171-2470b63dff00")); PowerMock.verifyAll(); }
First we will call the mockStaticPartial()
method of the org.powermock.api.easymock.PowerMock
class passing the class and the static method name as string which we want to mock:
PowerMock.mockStaticPartial(UUID.class, "randomUUID");
Then we will define the expectation by calling the expect method of EasyMock and returning the test value of the random UUID.
EasyMock.expect(UUID.randomUUID()).andReturn(UUID.fromString("067e6162-3b6f-4ae2-a171-2470b63dff00"));
Now we will call the replayAll()
method of PowerMock
.
PowerMock.replayAll();
It replays all classes and mock objects known by PowerMock. This includes all classes that are prepared for test using the PrepareForTest
or PrepareOnlyThisForTest
annotations and all classes that have had their static initializers removed by using the SuppressStaticInitializationFor
annotation. It also includes all mock instances created by PowerMock such as those created or used by createMock(Class, Method...)
, mockStatic(Class, Method...)
, expectNew(Class, Object...)
, createPartialMock(Class, String...)
etc.
To make it easy to pass in additional mocks not created by the PowerMock API you can optionally specify them as additionalMocks. These are typically those mock objects you have created using pure EasyMock or EasyMock class extensions. No additional mocks needs to be specified if you’re only using PowerMock API methods. The additionalMocks are also automatically verified when invoking the verifyAll()
method.
Now we will call the createUserId()
method of the UserController
class by passing in the test user details.
Assert.assertTrue(userController.createUserId(getNewUser()).contains("067e6162-3b6f-4ae2-a171-2470b63dff00"));
In the end we will call the verifyAll()
PowerMock.verifyAll();
It verifies all classes and mock objects known by PowerMock. This includes all classes that are prepared for test using the PrepareForTest
or PrepareOnlyThisForTest
annotations and all classes that have had their static initializers removed by using the SuppressStaticInitializationFor
annotation. It also includes all mock instances created by PowerMock such as those created or used by createMock(Class, Method...)
, mockStatic(Class, Method...)
, expectNew(Class, Object...)
, createPartialMock(Class, String...)
etc.
Note that all additionalMocks passed to the replayAll(Object...)
method are also verified here automatically.
6. Mock private methods
In this section we will see how we can mock a private method using PowerMock. It’s a very useful feature which uses java reflection. We will define a public method in out UserController class as below:
public String getGreetingText(User user) { return String.format(getGreetingFormat(), user.getFirstName(), user.getSurname()); }
As we can see that this method calls a private method getGreetingFormat()
, which is defined as below:
private String getGreetingFormat() { return "Hello %s %s"; }
We will try to change the behavior of this private method using PowerMock.
You can create spies of real objects. When you use the spy then the real methods are called (unless a method was stubbed). Spying on real objects can be associated with “partial mocking” concept. We will first create a spy on the UserController
class.
UserController spy = spy(new UserController());
Then we will define how the private method should behave when it’s been called by using org.powermock.api.mockito.PowerMockito.when
.
when(spy, method(UserController.class, "getGreetingFormat")).withNoArguments().thenReturn("Good Morning %s %s");
Now we will call the public method (which uses the private method) on the spied object
assertEquals("Good Morning Code Geeks", spy.getGreetingText(user));
Below is the code snippet of the whole method
@Test public void testMockPrivateMethod() throws Exception { UserController spy = spy(new UserController()); when(spy, method(UserController.class, "getGreetingFormat")).withNoArguments().thenReturn("Good Morning %s %s"); User user = new User(); user.setFirstName("Code"); user.setSurname("Geeks"); assertEquals("Good Morning Code Geeks", spy.getGreetingText(user)); }
7. Mock final classes
EasyMock does not allow you to mock a final class but PowerMock does. You can simple do
ExampleFinalClass clazz = PowerMock.createMock(ExampleFinalClass .class);
Below is the list of this which we need to do for mocking a final class:
- Use the @RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
- Use the @PrepareForTest(ClassWithFinal.class) annotation at the class-level of the test case.
- Use PowerMock.createMock(FinalClazz.class) to create a mock object for all methods of this class (let’s call it mockObject).
- Use PowerMock.replay(mockObject) to change the mock object to replay mode.
- Use PowerMock.verify(mockObject) to change the mock object to verify mode.
First we will create a very simple final class with just one final method.
SimpleFinalClazz.java
package com.javacodegeeks.powermock; public final class SimpleFinalClazz { public final String simpleFinalMethod() { return "Final String"; } }
Now we will define another class which will use this class.
FinalClazzUser.java
package com.javacodegeeks.powermock; public class FinalClazzUser { private SimpleFinalClazz simpleFinalClazz; public FinalClazzUser(SimpleFinalClazz simpleFinalClazz) { this.simpleFinalClazz = simpleFinalClazz; } public String getMeSomething() { return "Get Me Something " + simpleFinalClazz.simpleFinalMethod(); } }
Now we will see how we can mock the final class SimpleFinalClazz to change it’s behavior.
@Test public void testMockFinal() { SimpleFinalClazz simpleFinalClazz = PowerMock.createMock(SimpleFinalClazz.class); FinalClazzUser finalClazzUser = new FinalClazzUser(simpleFinalClazz); EasyMock.expect(simpleFinalClazz.simpleFinalMethod()).andReturn("Hurray!!!"); PowerMock.replay(simpleFinalClazz); String actual = finalClazzUser.getMeSomething(); PowerMock.verify(simpleFinalClazz); Assert.assertEquals(actual, "Get Me Something Hurray!!!"); }
First we will call the createMock() method of PowerMock and will pass the SimpleFinalClazz reference as the parameter to mock it.
SimpleFinalClazz simpleFinalClazz = PowerMock.createMock(SimpleFinalClazz.class);
Then we will create the instance of FinalClazzUser class by passing the mock object created above.
FinalClazzUser finalClazzUser = new FinalClazzUser(simpleFinalClazz);
Then we will define the expectation of the method defined in the final class.
EasyMock.expect(simpleFinalClazz.simpleFinalMethod()).andReturn("Hurray!!!");
Now we will replay the mock object.
PowerMock.replay(simpleFinalClazz);
Now we will verify the expected and actual behavior
PowerMock.verify(simpleFinalClazz); Assert.assertEquals(actual, "Get Me Something Hurray!!!");
8. Mock constructor
One of the biggest problems in writing unit-tests is the profligate use of “new” — i.e, constructors. When the class you want to test in turn explicitly constructs its dependencies, you may have a big problem. In this section we will see how we can use PowerMockito to mock contructors.
First we will define a simple class SimpleClass with one method getMeCurrentDateAsString()
package com.javacodegeeks.powermock.constructor; import java.util.Calendar; public class SimpleClass { @SuppressWarnings("deprecation") public String getMeCurrentDateAsString() { return Calendar.getInstance().getTime().toGMTString(); } }
Now we will define another class PowerMockConstructorExample which has the reference to the first class (SimpleClass)
package com.javacodegeeks.powermock.constructor; public class PowerMockConstructorExample { public String getMeSimpleObject() { SimpleClass simpleClass = new SimpleClass(); String returnValue = simpleClass.getMeCurrentDateAsString(); return returnValue; } }
Now we will see how we can mock the SimpleClass
class.
Annotate the SimpleClass reference with @Mock
annotation
@Mock private SimpleClass mockSimpleClass;
Now use the expectNew()
method of PowerMock to set the mock class instead of the real one. It allows specifying expectations on new invocations. Note that you must replay the class when using this method since this behavior is part of the class mock.
expectNew(SimpleClass.class).andReturn(mockSimpleClass);
Now we will define the method expectation like below
expect(mockSimpleClass.getMeCurrentDateAsString()).andReturn("Mock Result");
Now we will replay the mock class.
replay(SimpleClass.class, mockSimpleClass);
Now we verify the result
String value = instance.getMeSimpleObject(); verify(SimpleClass.class, mockSimpleClass); assertEquals("Mock Result", value);
Below is the full test class which we used to test this:
PowerMockConstructorExampleTest.java
package com.javacodegeeks.powermock.constructor; import static org.easymock.EasyMock.expect; import static org.powermock.api.easymock.PowerMock.expectNew; import static org.powermock.api.easymock.PowerMock.replay; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.easymock.annotation.Mock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.powermock.api.easymock.PowerMock.verify; import static org.junit.Assert.assertEquals; @RunWith(PowerMockRunner.class) @PrepareForTest(PowerMockConstructorExample.class) public class PowerMockConstructorExampleTest { @Mock private SimpleClass mockSimpleClass; private PowerMockConstructorExample instance; @Test public void testMockConstructor() throws Exception { instance = new PowerMockConstructorExample(); expectNew(SimpleClass.class).andReturn(mockSimpleClass); expect(mockSimpleClass.getMeCurrentDateAsString()).andReturn("Mock Result"); replay(SimpleClass.class, mockSimpleClass); String value = instance.getMeSimpleObject(); verify(SimpleClass.class, mockSimpleClass); assertEquals("Mock Result", value); } }
9. Download the source file
In this article we saw the usages of PowerMock and how it provides extra features which Mockito/EasyMock doesn’t provide..
You can download the full source code of this example here : PowerMockito
The testMockConstructor method failed due NullPointerException on line Nr.28. Fixed by this statement after line 25: mockSimpleClass = mock(SimpleClass.class);