Mocking static methods (Simple)

Exclusive offer: get 50% off this eBook here
Instant Mock Testing with PowerMock [Instant]

Instant Mock Testing with PowerMock [Instant] — Save 50%

Discover unit testing using PowerMock with this book and ebook

$14.99    $7.50
by Deep Shah | October 2013 | Open Source

In this article written by Deep Shah, the author of the book Instant Mock Testing with PowerMock shows how effortlessly we can mock static methods with PowerMock. Most of the mocking frameworks have trouble mocking static methods. But for Power Mock, it’s just another day at work.

The real power of PowerMock is the ability to mock things that other frameworks can't. One such thing is mocking static methods.

(For more resources related to this topic, see here.)

Getting ready

The use of static methods is usually considered a bad Object Oriented Programming practice, but if we end up in a project that uses a pattern such as active record (see http://en.wikipedia.org/wiki/Active_record_pattern), we will end up having a lot of static methods.

In such situations, we will need to write some unit tests and PowerMock could be quite handy.

Start your favorite IDE (which we set up in the Getting and installing PowerMock (Simple) recipe), and let's fire away.

How to do it...

  1. We will start where we left off. In the EmployeeService.java file, we need to implement the getEmployeeCount method; currently it throws an instance of UnsupportedOperationException.
  2. Let's implement the method in the EmployeeService class; the updated classes are as follows:

    /** * This class is responsible to handle the CRUD * operations on the Employee objects. * @author Deep Shah */ public class EmployeeService { /** * This method is responsible to return * the count of employees in the system. * It does it by calling the * static count method on the Employee class. * @return Total number of employees in the system. */ public int getEmployeeCount() { return Employee.count(); } } /** * This is a model class that will hold * properties specific to an employee in the system. * @author Deep Shah */ public class Employee { /** * The method that is responsible to return the * count of employees in the system. * @return The total number of employees in the system. * Currently this * method throws UnsupportedOperationException. */ public static int count() { throw new UnsupportedOperationException(); } }

  3. The getEmployeeCount method of EmployeeService calls the static method count of the Employee class. This method in turn throws an instance of UnsupportedOperationException.
  4. To write a unit test of the getEmployeeCount method of EmployeeService, we will need to mock the static method count of the Employee class.
  5. Let's create a file called EmployeeServiceTest.java in the test directory. This class is as follows:

    /** * The class that holds all unit tests for * the EmployeeService class. * @author Deep Shah */ @RunWith(PowerMockRunner.class) @PrepareForTest(Employee.class) public class EmployeeServiceTest { @Test public void shouldReturnTheCountOfEmployeesUsingTheDomainClass() { PowerMockito.mockStatic(Employee.class); PowerMockito.when(Employee.count()).thenReturn(900); EmployeeService employeeService = newEmployeeService(); Assert.assertEquals(900,employeeService.getEmployeeCount()); } }

  6. If we run the preceding test, it passes. The important things to notice are the two annotations (@RunWith and @PrepareForTest) at the top of the class, and the call to the PowerMockito.mockStatic method.
    • The @RunWith(PowerMockRunner.class) statement tells JUnit to execute the test using PowerMockRunner.
    • The @PrepareForTest(Employee.class) statement tells PowerMock to prepare the Employee class for tests. This annotation is required when we want to mock final classes or classes with final, private, static, or native methods.
    • The PowerMockito.mockStatic(Employee.class) statement tells PowerMock that we want to mock all the static methods of the Employee class.
    • The next statements in the code are pretty standard, and we have looked at them earlier in the Saying Hello World! (Simple) recipe. We are basically setting up the static count method of the Employee class to return 900. Finally, we are asserting that when the getEmployeeCount method on the instance of EmployeeService is invoked, we do get 900 back.
  7. Let's look at one more example of mocking a static method; but this time, let's mock a static method that returns void.
  8. We want to add another method to the EmployeeService class that will increment the salary of all employees (wouldn't we love to have such a method in reality?).
  9. Updated code is as follows:

    /** * This method is responsible to increment the salary * of all employees in the system by the given percentage. * It does this by calling the static giveIncrementOf method * on the Employee class. * @param percentage the percentage value by which * salaries would be increased * @return true if the increment was successful. * False if increment failed because of some exception* otherwise. */ public boolean giveIncrementToAllEmployeesOf(intpercentage) { try{ Employee.giveIncrementOf(percentage); return true; } catch(Exception e) { return false; } }

  10. The static method Employee.giveIncrementOf is as follows:

    /** * The method that is responsible to increment * salaries of all employees by the given percentage. * @param percentage the percentage value by which * salaries would be increased * Currently this method throws * UnsupportedOperationException. */ public static void giveIncrementOf(int percentage) { throw new UnsupportedOperationException(); }

  11. The earlier syntax would not work for mocking a void static method . The test case that mocks this method would look like the following:

    @RunWith(PowerMockRunner.class) @PrepareForTest(Employee.class) public class EmployeeServiceTest { @Test public void
    shouldReturnTrueWhenIncrementOf10PercentageIsGivenSuccessfully() { PowerMockito.mockStatic(Employee.class); PowerMockito.doNothing().when(Employee.class); Employee.giveIncrementOf(10); EmployeeService employeeService = newEmployeeService(); Assert.assertTrue(employeeService.
    giveIncrementToAllEmployeesOf(10)); } @Test public void
    shouldReturnFalseWhenIncrementOf10PercentageIsNotGivenSuccessfully() { PowerMockito.mockStatic(Employee.class); PowerMockito.doThrow(newIllegalStateException()).
    when(Employee.class);
    Employee.giveIncrementOf(10); EmployeeService employeeService = newEmployeeService(); Assert.assertFalse(employeeService.
    giveIncrementToAllEmployeesOf(10)); } }

  12. Notice that we still need the two annotations @RunWith and @PrepareForTest, and we still need to inform PowerMock that we want to mock the static methods of the Employee class.
  13. Notice the syntax for PowerMockito.doNothing and PowerMockito.doThrow:
    • The PowerMockito.doNothing method tells PowerMock to literally do nothing when a certain method is called. The next statement of the doNothing call sets up the mock method. In this case it's the Employee.giveIncrementOf method. This essentially means that PowerMock will do nothing when the Employee.giveIncrementOf method is called.
    • The PowerMockito.doThrow method tells PowerMock to throw an exception when a certain method is called. The next statement of the doThrow call tells PowerMock about the method that should throw an exception; in this case, it would again be Employee.giveIncrementOf. Hence, when the Employee.giveIncrementOf method is called, PowerMock will throw an instance of IllegalStateException.

How it works...

PowerMock uses custom class loader and bytecode manipulation to enable mocking of static methods. It does this by using the @RunWith and @PrepareForTest annotations.

The rule of thumb is whenever we want to mock any method that returns a non-void value , we should be using the PowerMockito.when().thenReturn() syntax. It's the same syntax for instance methods as well as static methods.

But for methods that return void, the preceding syntax cannot work. Hence, we have to use PowerMockito.doNothing and PowerMockito.doThrow. This syntax for static methods looks a bit like the record-playback style.

On a mocked instance created using PowerMock, we can choose to return canned values only for a few methods; however, PowerMock will provide defaults values for all the other methods. This means that if we did not provide any canned value for a method that returns an int value, PowerMock will mock such a method and return 0 (since 0 is the default value for the int datatype) when invoked.

There's more...

The syntax of PowerMockito.doNothing and PowerMockito.doThrow can be used on instance methods as well.

.doNothing and .doThrow on instance methods

The syntax on instance methods is simpler compared to the one used for static methods.

  1. Let's say we want to mock the instance method save on the Employee class. The save method returns void, hence we have to use the doNothing and doThrow syntax. The test code to achieve is as follows:

    /** * The class that holds all unit tests for * the Employee class. * @author Deep Shah */ public class EmployeeTest { @Test() public void shouldNotDoAnythingIfEmployeeWasSaved() { Employee employee =PowerMockito.mock(Employee.class); PowerMockito.doNothing().
    when(employee.save();
    try { employee.save(); } catch(Exception e) { Assert.fail("Should not have thrown anexception"); } } @Test(expected = IllegalStateException.class) public void shouldThrowAnExceptionIfEmployeeWasNotSaved() { Employee employee =PowerMockito.mock(Employee.class); PowerMockito.doThrow(newIllegalStateException()).
    when(employee).save();
    employee.save(); } }

  2. To inform PowerMock about the method to mock, we just have to invoke it on the return value of the when method. The line PowerMockito.doNothing().when(employee).save() essentially means do nothing when the save method is invoked on the mocked Employee instance.
  3. Similarly, PowerMockito.doThrow(new IllegalStateException()).when(employee).save() means throw IllegalStateException when the save method is invoked on the mocked Employee instance.
  4. Notice that the syntax is more fluent when we want to mock void instance methods.

Summary

In this article, we saw how easily we can mock static methods.

Resources for Article:


Further resources on this subject:


Instant Mock Testing with PowerMock [Instant] Discover unit testing using PowerMock with this book and ebook
Published: October 2013
eBook Price: $14.99
See more
Select your format and quantity:

About the Author :


Deep Shah

Deep Shah has been writing software for over a decade. As a child, he was always fascinated by computers. As time passed, his fascination grew into passion, and he decided to take up Software Development as a career choice. Deep has a degree in Computer Science and is a big fan of open source software. Being a Software Developer at heart, he likes exploring new programming languages, tools, and frameworks.

Deep strongly believes in writing unit tests. He thinks that any code (no matter when it’s written) that does not have unit tests is legacy code. Deep has served stints with companies such as Amazon, SpiderLogic, and ThoughtWorks. He speaks a number of languages including Java, C#, JavaScript, Scala, and Haskell. In his free time, Deep likes to see the world, go to cool places, and click lots of pictures.

Books From Packt


Spring 2.5 Aspect Oriented Programming
Spring 2.5 Aspect Oriented Programming

Object-Oriented Programming with PHP5
Object-Oriented Programming with PHP5

 Arquillian Testing Guide
Arquillian Testing Guide

 Instant Mockito [Instant]
Instant Mockito [Instant]

 Instant Testing with QUnit [Instant]
Instant Testing with QUnit [Instant]

 Web Services Testing with soapUI
Web Services Testing with soapUI

TestNG Beginner's Guide
TestNG Beginner's Guide

 Python Testing: Beginner's Guide
Python Testing: Beginner's Guide


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
U
X
X
M
x
u
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software