Powermock – Mockito Integration Example
Most of the mocking frameworks in Java, including Mockito, cannot mock static methods or final classes. If we come across a situation where we need to test these components, we won’t be able to unless we re-factor the code and make them testable. For example:
- Making private methods packaged or protected
- Avoiding static methods
But re-factoring at the cost of good design may not always be the right solution.
In such scenarios, it makes sense to use a testing framework like Powermock which allows us to mock even the static, final and private methods.
Good thing about Powermock is that it doesn’t re-invent the testing framework and in fact enhances the testing frameworks like Easymock and Mockito.
In this article, we will see an integration example of Powermock and Mockito but first let’s do the setup.
Below are my setup details:
- I am using Maven – the build tool
- Eclipse as the IDE, version Luna 4.4.1.
- JUnit is my testing framework.
- Add Mockito and PowerMockito dependencies to our
pom.xml
.
1. Dependencies in pom.xml
Our dependencies consist of:
junit
mockito-core
powermock-api-mockito
powermock-module-junit4
pom.xml:
<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>com.javacodegeeks.testng.maven</groupId> <artifactId>testngMaven</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.0.5-beta</version> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.2</version> <scope>test</scope> </dependency> </dependencies> </project>
2. System Under Test (SUT)
Our system under test is a system called SomeSystem
which owns some services. A service is defined by Service
interface which has couple of methods getName()
and start()
. If the start of the service is successful it will return 1 else 0.
One can add a Service
to the SomeSystem
using add(service)
method. Our SubSystem
has a start()
method which will start the services it contains. On start of each service, ServiceListener
is notified of the success or failure of the service.
SomeSystem:
package com.javacodegeeks.mockito; import java.util.ArrayList; import java.util.List; public class SomeSystem { private List services = new ArrayList(); private ServiceListener serviceListener; private List events = new ArrayList(); public void start() { for (Service service : services) { boolean success = startServiceStaticWay(service) > 0; notifyServiceListener(serviceListener, service, success); addEvent(service, success); } } private void addEvent(Service service, boolean success) { events.add(getEvent(service.getName(), success)); } private String getEvent(String serviceName, boolean success) { return serviceName + (success ? "started" : "failed"); } public static void notifyServiceListener(ServiceListener serviceListener, Service service, boolean success) { if (serviceListener != null) { if (success) { serviceListener.onSuccess(service); } else { serviceListener.onFailure(service); } } } public void add(Service someService) { services.add(someService); } public static int startServiceStaticWay(Service service) { int returnCode = service.start(); return returnCode; } public void setServiceListener(ServiceListener serviceListener) { this.serviceListener = serviceListener; } public List getEvents() { return events; } }
Service:
package com.javacodegeeks.mockito; public interface Service { String getName(); int start(); }
ServiceListener:
package com.javacodegeeks.mockito; public interface ServiceListener { void onSuccess(Service service); void onFailure(Service service); }
3. Integrate PowerMockito and Mockito
In setupMock()
, we will set up our system. We will create mock objects for Service
and ServiceListener
using Mockito.mock. B
oth are interfaces and we don’t have the actual implementations ready. Since SomeSystem
is our SUT, we will create a spy object of it so that later we can stub some of its behavior.
Now let’s come to our first test startSystem
:
- We will stub
service.start()
using PowerMockito so that it returns 1. - Next, we start the system calling
system.start()
- Finally, we will verify the behavior using Mockito’s
verify()
APIMockito.verify(serviceListener).onSuccess(service);
Notice that we stub using PowerMockito but verify using Mockito. This shows that Powermock doesn’t re-invent the wheel rather enhances the existing testing frameworks.
PowerMockitoIntegrationExample:
package com.javacodegeeks.mockito; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) public class PowerMockitoIntegrationExample { private Service service; private SomeSystem system; private ServiceListener serviceListener; @Before public void setupMock() { // Mock service = Mockito.mock(Service.class); serviceListener = Mockito.mock(ServiceListener.class); system = Mockito.spy(new SomeSystem()); system.add(service); system.setServiceListener(serviceListener); } @Test public void startSystem() { // Stub using Mockito and PowerMockito p("Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful"); PowerMockito.when(service.start()).thenReturn(1); // Run p("Start the system, should start the services in turn"); system.start(); // Verify using Mockito p("Verify using Mockito that service started successfuly"); Mockito.verify(serviceListener).onSuccess(service); p("Verifed. Service started successfully"); } private void p(String s) { System.out.println(s); } }
Output:
Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful Start the system, should start the services in turn Verify using Mockito that service started successfuly Verifed. Service started successfully
4. Mocking Static Method
The use of static methods goes against the Object Oriented concepts but in real world we still use a lot of static methods and there are times when it makes sense to use static methods. Nevertheless, the ability to mock static methods may come handy to us. In this example, we will stub a static non-void method.
In the beginning of test class you will notice @RunWith
annotation that contains PowerMockRunner.class
as value. This statement tells JUnit to execute the test using PowerMockRunner
.
You may also see annotation @PrepareForTest
which takes the class to be mocked. This is required when we want to mock final classes or methods which either final, private, static or native.
We will use PowerMockito.mockStatic
statement which takes in the class to be mocked. It tells PowerMockito to mock all the static methods. We then stub the static method’s behavior.
For example, in stubStaticNonVoidMethod
, we stub SomeSystem.startServiceStaticWay
to return 1.
PowerMockito.when(SomeSystem.startServiceStaticWay(service)).thenReturn(1);
PowerMockitoStaticMethodExample:
package com.javacodegeeks.mockito; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) public class PowerMockitoStaticMethodExample { private Service service; private SomeSystem system; private ServiceListener serviceListener; @Before public void setupMock() { // Mock service = Mockito.mock(Service.class); serviceListener = Mockito.mock(ServiceListener.class); system = new SomeSystem(); //system = Mockito.spy(new SomeSystem()); system.add(service); system.setServiceListener(serviceListener); } @Test public void stubStaticNonVoidMethod() { // Stub static method startServiceStatic to start successfully p("Call mockStatic SomeSystem.class to enable static mocking"); PowerMockito.mockStatic(SomeSystem.class); p("Stub static method startServiceStaticWay to return 1"); PowerMockito.when(SomeSystem.startServiceStaticWay(service)) .thenReturn(1); // Run p("Start the system, should start the services in turn"); system.start(); // Verify success p("Verify using Mockito that service started successfuly"); Mockito.verify(serviceListener).onSuccess(service); // Stub static method startServiceStatic to fail p("Stub static method startServiceStaticWay to return 0"); PowerMockito.when(SomeSystem.startServiceStaticWay(service)) .thenReturn(0); // Run p("Start the system again"); system.start(); // Verify failure p("Verify using Mockito that service has failed"); Mockito.verify(serviceListener).onFailure(service); } private void p(String s) { System.out.println(s); } }
Output:
Call mockStatic SomeSystem.class to enable static mocking Stub static method startServiceStaticWay to return 1 Start the system, should start the services in turn Verify using Mockito that service started successfuly Stub static method startServiceStaticWay to return 0 Start the system again Verify using Mockito that service has failed
5. Mocking static void Method
In this example, we will mock a void static method. The first step would be to call PowerMockito.mockStatic
similar to the static non-void method. Since a void method doesn’t return anything, the earlier way of mocking static methods won’t work here.
PowerMockito.doNothing().when(SomeSystem.class);
Next, we will stub the behavior. After stubbing, we will call the static method on which it applies.
SomeSystem.notifyServiceListener(serviceListener, service, true);
We will follow similar style for verifying a static void method.
PowerMockito.verifyStatic(); SomeSystem.startServiceStaticWay(service);
PowerMockitoStaticVoidMethodExample:
package com.javacodegeeks.mockito; import org.junit.Before; 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) public class PowerMockitoStaticVoidMethodExample { private Service service; private SomeSystem system; private ServiceListener serviceListener; @Before public void setupMock() { service = Mockito.mock(Service.class); serviceListener = Mockito.mock(ServiceListener.class); system = new SomeSystem(); system.add(service); system.setServiceListener(serviceListener); } @PrepareForTest({ SomeSystem.class }) @Test public void stubStaticVoidMethod() { p("Call mockStatic SomeSystem.class to enable static mocking"); PowerMockito.mockStatic(SomeSystem.class); p("Stub static void method SomeSystem.notifyServiceListener to do nothing"); PowerMockito.doNothing().when(SomeSystem.class); SomeSystem.notifyServiceListener(serviceListener, service, true); p("Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful"); PowerMockito.when(service.start()).thenReturn(1); p("Start the system"); system.start(); p("Verify static method startServiceStaticWay(service) is called"); PowerMockito.verifyStatic(); SomeSystem.startServiceStaticWay(service); p("Verify serviceListener.onSuccess(service) is not called as notifyServiceListener is stubbed to do nothing"); Mockito.verify(serviceListener, Mockito.never()).onSuccess(service); } private void p(String s) { System.out.println(s); } }
Output:
Call mockStatic SomeSystem.class to enable static mocking Stub static void method SomeSystem.notifyServiceListener to do nothing Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful Start the system Verify static method startServiceStaticWay(service) is called Verify serviceListener.onSuccess(service) is not called as notifyServiceListener is stubbed to do nothing
6. Subbing Private Method
Using PowerMockito we can stub as well as verify private methods. In this example, I will show you how to stub a private method.
Our private method addEvent
adds an event to the list. The event will tell us know whether a service started successfully or failed. Since we can’t access the private method, we will have to pass the SUT object, private method name along with the method arguments to PowerMockito.doNothing().when()
method.
In test case stubPrivateMethodAddEvent
, we stub addEvent
to do nothing.
PowerMockito.doNothing().when(system, "addEvent", service, true)
In test case stubPrivateMethodGetEventString
, we stub getEvent
to return some hardcoded string.
PowerMockito.when(system, "getEvent", serviceA, true).thenReturn(serviceA_is_successful);
PowerMockitoStubPrivateMethodExample:
package com.javacodegeeks.mockito; import org.junit.Before; 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; import org.junit.Assert; @PrepareForTest({ SomeSystem.class }) @RunWith(PowerMockRunner.class) public class PowerMockitoStubPrivateMethodExample { private Service service; private SomeSystem system; private ServiceListener serviceListener; @Before public void setupMock() { // Mock service = Mockito.mock(Service.class); serviceListener = Mockito.mock(ServiceListener.class); system = PowerMockito.spy(new SomeSystem()); system.add(service); system.setServiceListener(serviceListener); } @Test public void stubPrivateMethodAddEvent() throws Exception { p("Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful"); PowerMockito.when(service.start()).thenReturn(1); p("Stub service name to return serviceA"); Mockito.when(service.getName()).thenReturn("serviceA"); p("Stub private addEvent to do nothing"); PowerMockito.doNothing().when(system, "addEvent", service, true); p("Start the system, should start the services in turn"); system.start(); p("Since we have stubbed addEvent, assert that system.getEvents() is empty"); Assert.assertTrue(system.getEvents().isEmpty()); } @Test public void stubPrivateMethodGetEventString() throws Exception { final String serviceA = "serviceA"; final String serviceA_is_successful = serviceA + " is successful"; p("Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful"); PowerMockito.when(service.start()).thenReturn(1); p("Stub service name to return serviceA"); Mockito.when(service.getName()).thenReturn(serviceA); p("Stub private addEvent to do nothing"); PowerMockito.when(system, "getEvent", serviceA, true).thenReturn(serviceA_is_successful); p("Start the system, should start the services in turn"); system.start(); p("Since we have stubbed getEvent, assert that system.getEvents() contains the event string"); Assert.assertTrue(!system.getEvents().isEmpty()); Assert.assertEquals(serviceA_is_successful, system.getEvents().get(0)); System.out.println(system.getEvents()); } private void p(String s) { System.out.println(s); } }
In stubPrivateMethodAddEvent
, since we have stubbed addEvent
to do nothing, no events will added to the list.
In stubPrivateMethodGetEventString
, we confirm that the event string we have returned is found in the events.
Output:
Test stubPrivateMethodAddEvent: Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful Stub service name to return serviceA Stub private addEvent to do nothing Start the system, should start the services in turn Since we have stubbed addEvent, assert that system.getEvents() is empty Test stubPrivateMethodGetEventString: Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful Stub service name to return serviceA Stub private addEvent to do nothing Start the system, should start the services in turn Since we have stubbed getEvent, assert that system.getEvents() contains the event string [serviceA is successful]
7. Verifying Private Method
Verification is similar to stubbing and PowerMockito allows us to verify even the private methods. The name of the method is passed to the PowerMockito.verifyPrivate
along with its arguments.
PowerMockito.verifyPrivate(system).invoke("addEvent", new Object[] { service, true });
PowerMockitoVerifyPrivateMethodExample:
package com.javacodegeeks.mockito; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) public class PowerMockitoVerifyPrivateMethodExample { private Service service; private SomeSystem system; private ServiceListener serviceListener; @Before public void setupMock() { // Mock service = Mockito.mock(Service.class); serviceListener = Mockito.mock(ServiceListener.class); system = Mockito.spy(new SomeSystem()); system.add(service); system.setServiceListener(serviceListener); } @Test public void verifyPrivateMethods() throws Exception { p("Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful"); PowerMockito.when(service.start()).thenReturn(1); p("Stub service name to return serviceA"); Mockito.when(service.getName()).thenReturn("serviceA"); p("Start the system, should start the services in turn"); system.start(); p("Verify private method addEvent(service, true) is called"); PowerMockito.verifyPrivate(system).invoke("addEvent", new Object[] { service, true }); p("Verified private method is called"); } private void p(String s) { System.out.println(s); } }
Output:
Stub using PowerMockito. service.start() should return 1 as we want start of the service to be successful Stub service name to return serviceA Start the system, should start the services in turn Verify private method addEvent(service, true) is called Verified private method is called
8. Download Source Code
This example was about PowerMockito and Mockito integration.
You can download the full source code of this example here: powerMockitoIntegration.zip
Getting – NoClassDefFoundError: org/junit/internal/runners/TestClass
please help.
How you are saving the list of service because Service is an interface not model class