PowerMock (Android)

Often to write unit tests encounter difficulties and sometimes we need to sacrifice good design for testing purposes only. An example is to make public attributes or methods, which otherwise with JUnit and other Mock frameworks we could not achieve. Other cases are related to the fact that they cannot use methods or final classes, static methods. A solution to these problems is PowerMock!

PowerMock logo

PowerMock is a framework that extends other mock libraries such as Mockito and EasyMock, but adds more capacity. PowerMock uses custom classloader and bytecode manipulation to allow mocking of static methods, builders, final classes, private methods and more. So we can test our code without modifying it, thanks to the fact that the mock objects are hooked to the code to be tested in execution time. By using reflection this framework allows you to modify even private attributes of the class.

We remember that Java allows you to build dynamically extendable applications, meaning that an application is able to load, in runtime, new code and run it, including the code that did not even exist when the application was written. Java in fact dynamically loads the classes, i. e. it loads the class information during program execution. This upload is handled by a ClassLoader object, a class provided by Java. A ClassLoader then imports binary data that defines the classes (and interfaces) of a running program.

Android Studio Configuration

PowerMock seems to have less rapid development than Mockito, so we can’t use it together with the latest version of Mockito. Nothing insurmountable, but it is important to know this aspect in order not to incur strange exceptions during the tests. The table below shows the versions of Mockito supported by the various versions of PowerMock.

Supported versions

In my tests the PowerMock version 1.7.0RC2 was used, so the code to enter in build. gradle is as shown below:

The last two dependencies are used to use PowerMock together with JUnit and to take advantage of the APIs offered by Mockito version 2.Utilizzo di PowerMock

Annotations can be used to explicitly explain the use of PowerMock with JUnit.

The first annotation tells JUnit to test with PowerMock. The second annotation tells PowerMock to prepare classes for testing. In practice, we indicate the classes for which we want to manipulate bytecode. These annotations are required if we want to create mock of final classes or classes with private, final or static methods.
With the code in the fourth line we express the intention to create a mock object of Button class (Android Framework).

In general, in the @PrepareForTest annotation, enter the class class to be tested, while with mock() we create the mock object to simulate a dependency of the class under test..

Note: We take care to import static org.powermock.api.mockito.PowerMockito.mock; and not import org.mockito.Mock; to avoid run-time exception.

Whitebox

Whitebox is a PowerMock class that provides various static methods for bypassing encapsulation. This class uses Java reflection. The static methods are as follows:

  • With Whitebox.setInternalState(..) we can set a private attribute of the class;
  • With Whitebox.getInternalState(..) we can retrieve an object or a value of a class attribute;
  • With Whitebox.invokeMethod(..) we can invoke private method of the object of a class;
  • With Whitebox.invokeConstructor(..) we can create an instance of a class with private builder.

Let’s analyze in detail the first three.

As parameters we have:

  • tested: which is the class we are testing;
  • classattributename: is the name of the private attribute that we want to set;
  • value: is the value of that class attribute, we note that if it is a simple int we pass a numerical value, while if it is another class we can pass a mock object of that class.

As parameters we have:

  • tested: which is the class we are testing;
  • classattributename: is the name of the private attribute that we want to recover;
  • returnValue: is the value of that class attribute, returned by the getInternalState () method, which can be a simple whole value or the reference of an object.

As parameters we have:

  • tested: that’s the class we test;
  • method: it is the name of the private or protected method that we want to invoke;
  • param…: we can enter one or more parameters based on the method signature.

Mock and Spy

When using PowerMock, mock and spy objects must be created differently from Mockito.

In terms of functionality they are similar to those already explained for Mockito. We note that Spy invokes the real version only of the methods implemented in that class and does not invoke the true implementation of the parent class methods, except for Override.

PowerMockito Method

We note that there are methods that are proper to PowerMock, such as mock(Classe.class). But there are PowerMock methods with the same name as Mockito methods. These methods are from PowerMockito, which is a class that extends the functionality of Mockito with new features such as mocking of private or static methods. We note that, as recommended by PowerMock documentation, even if the methods have the same name as Mockito, you need to use PowerMockito where applicable. This is done practically by paying attention to imports or by explicitly using PowerMockito.method(…)
Let’s analyze suppress:

The suppress method makes it possible to suppress the execution of a method within the code we are testing. We can suppress private, protected and public methods. Note that:

  • method(TestClass.class): this indicates the class in which the method to be suppressed is located;
  • nomeMetodo: is the name of the method to be suppressed.

To verify that a static method is invoked within our code we can use verifyStatic:

A fundamental aspect to make verifyStatic method work is important that the order of the instructions is the one mentioned above, i. e. first line 1 and then the static method that we want to verify.

Let’s suppose you test a method of a ClassA inheriting from ClassB. In case we want to test in isolation the classA method that calls the constructor or a class B method, we can suppress all calls to the parent class. The code is as follows:

In case we want to create a mock of a static method of a certain class we can do this way (mockStatic):

Con:

  • mockStatic: is indicated to PowerMock the class with static methods;
  • PowerMockito.when: allows us to create the fake method for static method methodStatic().

We note that when it is also a method of Mockito, but we can’t use Mockito.when since PowerMockito.when is a “enhanced” version of when it allows us to treat static methods.

With PowerMock it is possible to intercept the constructor’s call of a particular class in order to pass the mock or spy object created by us.

TestClass is the name of the class for which we want to intercept the constructor, with withArguments(..) we indicate which constructor, then with what parameters, must be intercepted to return our mockObject.

Advantages and disadvantages

In summary, the advantages of PowerMock are:

  • Given its potential it almost never makes it necessary to modify the source code for testing purposes;
  • Provides a high amount of APIs to test public, private, static and final classes and methods;
  • Can be used in conjunction with Mockito and EasyMock.

Disadvantages:

  • Its development is slower than Mockito Framework and therefore it is not always possible to use the latest Mockito APIs;
  • The documentation is not exhaustive and precise like that of Mockito;
  • There are relatively few examples of PowerMock compared to Mockito.