Mock Testing using PowerMock (With JUnit and Mockito)

PowerMock is an open source mocking library for the Java world. It extends the existing mocking frameworks, such as EasyMock and Mockito, to add even more powerful features to them. PowerMock enables us to write good unit tests for even the most untestable code. Most of the mocking frameworks in Java cannot mock static methods or final classes. But using PowerMock, we can mock almost any class.

PowerMock currently extends the EasyMock and Mockito mocking frameworks. Depending on which extension is preferred, the syntax to write any unit test differs slightly. In this tutorial, I am using PowerMock with Mockito.

This tutorial will demonstrate a very simple mocking example using PowerMock. It will show us the basic syntax for creating a mock and verifying a method invocation.

PowerMock Installation With Dependencies

PowerMock is an open source mocking framework that is under active development. You can have setup in your machine in following steps.

1) Let’s start by downloading PowerMock 1.5. Visit PowerMock home at http://code.google.com/p/powermock/.

2) Click on the Downloads Tab on the page and you should see something as follows:

powermock download page

3) Since we are going to develop all our examples using the Mockito extension and JUnit test framework, download the powermock-mockito-junit-1.6.zip file.

4) Extract the ZIP file in some folder. This ZIP file has all the dependent JAR files that we will need for writing unit tests with PowerMock.

5) Copy all jar files into lib folder of your project, and add them as dependency.

You are done !!

You may need to additionally include “hamcrest-core-1.3.jar” if you do not have already.

Participant Classes

For the sake of completeness, let me write down below classes first which we will be using in test examples.

Employee.java

public class Employee {
	private String fName;

	public String getfName() {
		return fName;
	}

	public void setfName(String fName) {
		this.fName = fName;
	}
}

EmployeeService.java

public class EmployeeService 
{
	public int getEmployeeCount() {
		throw new UnsupportedOperationException();
	}
	
	public void saveEmployee(Employee employee) {
        //return nothing
    }
}

EmployeeController.java

public class EmployeeController 
{
	private EmployeeService employeeService;

    public EmployeeController(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    public int getProjectedEmployeeCount()
    {
        final int actualEmployeeCount = employeeService.getEmployeeCount();
        return actualEmployeeCount * 2;
    }
    
    public void saveEmployee(Employee employee) {
        employeeService.saveEmployee(employee);
    }
}

First Test without PowerMock

Let’s write a simple test to get employee count without using mock. As you see that EmployeeService.getEmployeeCount() method throws UnsupportedOperationException, the test should fail.

@Test
public void shouldGetCountOfEmployees()
{
	EmployeeController employeeController =new EmployeeController(new EmployeeService());
	Assert.assertEquals(10,employeeController.getProjectedEmployeeCount());
}

As you run the test, it surely fails with below exception.

java.lang.UnsupportedOperationException
	at com.howtodoinjava.powermock.examples.service.EmployeeService.getEmployeeCount(EmployeeService.java:8)
	at com.howtodoinjava.powermock.examples.controller.EmployeeController.getProjectedEmployeeCount(EmployeeController.java:16)
	at com.howtodoinjava.powermock.examples.test.EmployeeControllerTestOne.shouldGetCountOfEmployees(EmployeeControllerTestOne.java:15)

This can be scenario in any application where you are not allowed to use a certain method, and reasons can be unlimited. In this case, you may want to mock above method so that other part of your application could be tested.

Mock a simple method using PowerMock

In above example, getEmployeeCount() method is not supported but we want to use it. In this case, we can mock it using powermock.

@Test
public void firstMockTest() 
{
	//Creating a mock using the PowerMockito.mock
	//method for the EmployeeService class.
	EmployeeService mock =PowerMockito.mock(EmployeeService.class);

	//Next statement essentially says that when getProjectedEmployeeCount method
	//is called on the mocked EmployeeService instance, return 8.
	PowerMockito.when(mock.getEmployeeCount()).thenReturn(8);

	EmployeeController employeeController = new EmployeeController(mock);
	
	Assert.assertEquals(16, employeeController.getProjectedEmployeeCount());
}

Above test will execute successfully. Here, when employeeController.getProjectedEmployeeCount() is invoked, it in turn invoke the method getEmployeeCount() from mock object which return value 8. Controller multiplies it with 2, and return value is 16. This return value is equal to expected value in assert statement, so the test is passed.

Verify if mock method was really invoked?

Sometimes, unit test only need to call a method and forget it. Mostly because method does not return any value. You can certainly test whether value is present in DB by fetching it again from data source. But if your test only require to validate that a method was called and that’s it, the you can do it as well using powermock.

@Test
public void verifyMethodInvokationTest() 
{
	EmployeeService mock =PowerMockito.mock(EmployeeService.class);
	EmployeeController employeeController = new EmployeeController(mock);

	Employee employee = new Employee();
	employeeController.saveEmployee(employee);

	//Verifying that controller did call the
	//saveEmployee() method on the mocked service instance.
	Mockito.verify(mock).saveEmployee(employee);
}

In above test example, using verify(mock) method, we are verifying the saveEmployee(employee) was invoked indeed. If you run above test, this will pass.

To verify that above code is working perfectly, comment out below line from EmployeeController.java.

public void saveEmployee(Employee employee) {
	//employeeService.saveEmployee(employee); //Comment this line
}

Now if you will run the test again, it will fail with this error.

Wanted but not invoked:
employeeService.saveEmployee(
    com.howtodoinjava.powermock.examples.model.Employee@7808b9
);
-> at com.howtodoinjava.powermock.examples.test.EmployeeControllerTestOne.verifyMethodInvokationTest(EmployeeControllerTestOne.java:47)
Actually, there were zero interactions with this mock.

This is very good feature you can you in your unit tests.

Using mock settings for extra information about test run

These mock settings are rarely used but can be useful in some of the case. Use them if you want to name the mocks for future debugging purpose; or you want to enable verbose logging for extra information. You can use it when you want to register a listener for notifying method invocations on the mock; or even implementing few extra interfaces on mock which actual object has not implemented.

@Test
public void mockSettingsTest() {
	EmployeeService mock =PowerMockito.mock(EmployeeService.class, Mockito
		.withSettings()
		.name("EmployeeServiceMock")
		.verboseLogging());
	EmployeeController employeeController = new EmployeeController(mock);

	Employee employee = new Employee();
	employeeController.saveEmployee(employee);

	//Verifying that controller did call the
	//saveEmployee method on the mocked service
	//instance.
	Mockito.verify(mock).saveEmployee(employee);
}

Run above test to get below result in console:

############ Logging method invocation #1 on mock/spy ########
employeeService.saveEmployee(
    com.howtodoinjava.powermock.examples.model.Employee@c9131c
);
   invoked: -> at com.howtodoinjava.powermock.examples.controller.EmployeeController.saveEmployee(EmployeeController.java:21)
   has returned: "null"

############ Logging method invocation #2 on mock/spy ########
employeeService.saveEmployee(
    com.howtodoinjava.powermock.examples.model.Employee@c9131c
);
   invoked: -> at com.howtodoinjava.powermock.examples.test.EmployeeControllerTestOne.mockSettingsTest(EmployeeControllerTestOne.java:64)
   has returned: "null"

That’s all for this beginner tutorial on powermock to get you started. I will cover some complex topics in next set of tutorials.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

6 thoughts on “Mock Testing using PowerMock (With JUnit and Mockito)”

  1. Its being very helpful if you will explain some more examples to mock private methods ,static methods , public private constructor and one of the important mocking of DB connections…hope you will reply ,,Thanks ….

    Reply
  2. Hi Lokesh,

    How can i write Junit test using EasyMock or Mockito for spring rest controller till persistence layer. I was trying to write the way you have explained above but it says “Failed to load Application context”. Even I have use “@ContextConfiguration(locations = {“applicationContext.xml”})”. I have also placed it in src/test/resource folder.

    And the other thing I cannot use postman also because it has authenticate using authentication token. It’s being developed on liferay portlets. So every time I have to deploy my application on server I mean have to start the server and it takes lot of time also.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.