8. Other test unit frameworks
8.1 Mockito
8.2 Powermock
The purpose of the unit testing is to test the code without testing its dependencies.
For example, let’s say we want to test a method that takes the list of intergers and calculates the sum. From Unit testing standpoint, the scope of the test case is to verify if the sum of integers is performed correctly (in other words how the list is being used) and not how the List collection works.
// web.xml import java.util.List; public class MyClass { public int sum(List<Integer>elements){ intresult = 0; for (Integer element : elements){ result += element; } returnresult; } }
Sometimes the methods are dependent on other real time objects. So there are Mocking frameworks available that can be used to mock the dependent objects in the place of the real objects.
Principal mocking concepts
Three major mocking concepts are-
- stubbing
- setting expectations
- verifying
Stubbing
Stubbing is a process that establishes the test behavior. Stubbed function may indicate the behavior of the function based on how it has been invoked. For example the function should return a certain value, throw an error or dispatch an event.
Note: Only public properties and public functions can be stubbed.
Setting expectations
Setting expectations is the process that specifies the expected output of the method.
Verifying
Verifying is the process that happens after setting expectations. In this process, whether the expectations are met or not is verified. If the expectations are not met means that the unit test has failed.
8.1 Mockito
Mockito is a mock library for Java Objects and is released under the MIT License.
You can add the dependencies to add the Mockito in the project using pom.xml file or can be downloaded directly from http://mockito.org/.
Sample pom.xml file looks like below :
<projectxmlns="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.organization.somecompany</groupId> <artifactId>myapp</artifactId> <version>0.0.1-SNAPSHOT</version> <name>My Application</name> <description>Project example for Mockito</description> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> </dependencies> </project>
This framework is different from other mocking frameworks because it allows the testing without establishing expectations.
Mock objects can be created manually (via code) or with a mock framework that can simulate the classes. One of the mock object usage is a data provider which is needed to simulate the database objects like connections etc.
The mock objects can be created in two ways –
- with the static method mock(class)- MockitoAnnotations.initMocks(this) method call
- with @Mock annotation- By annotating the class with
@RunWith(MockitoJUnitRunner.class) annotation.
Note: Final classes, anonymous classes, static methods and primitive types cannot be tested with Mockito framework. Similarly equals() and hashCode() methods cannot be mocked.
For example, we can test a simple interface:
public interface IBox { public void setSize(int size); public int getSize(); public int getArea(); public boolean needsToBeResized(); }
The static method mock() takes the class as an argument and returns an object of that class. In our example an IBox object is created.
IBox myIbox = Mockito.mock(IBox.class);
The type of the created object can be checked with instanceOf operator, demonstrating that is a legal instance of the type IBox.
Import org. junit. Test; import static org.mockito.Mockito.*; import static org.junit.Assert.assertTrue; publicclass MyMockitoTest { private IBox myLittleIBox = mock(IBox.class); @Test publicvoid testIfIBoxIsIBox() { assertTrue(myLittleIBoxinstanceof IBox); } }
The result in Eclipse is:
Mockito can return default values when its methods are being called:
import org.junit.Test; import static org.mockito.Mockito.*; import static org.junit.Assert.*; publicclass MyMockitoDefaultValuesTest { private IBox myLittleIBox = mock(IBox.class); @Test publicvoid testDefaultBehaviourOfTestDouble() { assertFalse("new test double should return false as boolean", myLittleIBox.needsToBeResized()); assertEquals("new test double should return 0 as integer", 0, myLittleIBox.getSize()); } }
Below figure shows the result after running the test in Eclipse is:
The mocked object (myLittleIBox in our example) can return the desired values.
import org.junit.Test; import static org.mockito.Mockito.*; import static org.junit.Assert.*; publicclass MyMockitoDesiredValuesTest { private IBox myLittleIBox = mock(IBox.class); @Test publicvoid testStubbing() { assertFalse("new test double should return false as boolean", myLittleIBox.needsToBeResized()); when(myLittleIBox.needsToBeResized()).thenReturn(true); assertTrue("after instructed test double should return what we want",myLittleIBox.needsToBeResized()); } }
The result in Eclipse is:
Code Details::
Statement when(myLittleIBox.needsToBeResized()).thenReturn(true);
is readable and its meaning is “return true if myLittleBox needs to be resized”
We can throw exception as shown in below example.
import org.junit.Test; import static org.mockito.Mockito.*; publicclass MyMockitoThrowingExceptionsTest { private IBox myLittleIBox = mock(IBox.class); @Test(expected = RuntimeException.class) publicvoid throwException() { when(myLittleIBox.needsToBeResized()).thenThrow(new RuntimeException()); myLittleIBox.needsToBeResized(); } }
In abov code mocke object (myLittleIBox) will throw the exception .The expectations are set with “..thenThrow” statement.
The test passes because throws an exception when the method needsToBeResized() is executed.
We can verify if the methods have been called or not with Mockito. This can be done by calling verify() method on the mocked object ( in our case myLittleIBox).
import static org.mockito.Mockito.*; import org.junit.Test; publicclass MyMockitoVerificationTest { private IBox myLittleIBox = mock(IBox.class); @Test publicvoid testVerification() { myLittleIBox.setSize(12); myLittleIBox.needsToBeResized(); verify(myLittleIBox).setSize(12); verify(myLittleIBox).needsToBeResized(); } }
The test passes in Eclipse:
We can read the test as: “verify if myLittleIBox was asked to set size 12 “.
8.2 Powermock
Mockito framework does not have the ability to mock final and static methods, singletons, constructors and private methods. If we want to mock these kind of methods, then we need to use PowerMock framework with PowerMockito.
The framework can be added as dependency in pom.xml file. Refer below sample pom.xml (Exclusions are used in order to avoid confusions and potential version inconsistencies.)
<projectxmlns="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.organization.somecompany</groupId> <artifactId>myapp</artifactId> <version>0.0.1-SNAPSHOT</version> <name>My Application</name> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.5.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.5.5</version> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> <exclusion> <groupId>org.powermock</groupId> <artifactId>powermock-core</artifactId> </exclusion> <exclusion> <groupId>org.powermock</groupId> <artifactId>powermock-reflect</artifactId> </exclusion> </exclusions> <scope>test</scope> </dependency> </dependencies> </project>
Let's create two classes, one with final method and other with static method:
public class MyFinalClass { public final String printString(String s) { returns; } } public class MyStaticClass { public static final String printString(String s) { returns; } }
Below code is the unit test cases of the classes:
package powermock; import myapp.MyFinalClass; import myapp.MyStaticClass; import org.junit.Assert; 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) @PrepareForTest({MyFinalClass.class, MyStaticClass.class}) publicclass MyPowerMockTest { @Test publicvoid mockFinalClassTest() { MyFinalClass tested = PowerMockito.mock(MyFinalClass.class); final String mytestInput = "My test input"; final String mymockedResult = "Mocked final print result - " + mytestInput; Mockito.when(tested.printString(testInput)).thenReturn(mymockedResult); // Assert the mocked result is returned from method call Assert.assertEquals(tested.printString(mytestInput), mymockedResult); } @Test publicvoid mockStaticClassTest() { PowerMockito.mockStatic(MyStaticClass.class); final String mytestInput = "My test input"; final String mymockedResult = "Mocked static print result - " + mytestInput; Mockito.when(MyStaticClass.printString(testInput)).thenReturn(mymockedResult); // Assert the mocked result is returned from method call Assert.assertEquals(MyStaticClass.printString(mytestInput), mymockedResult); } }
The result after running the test in Eclipse is: