By default, when we run our local unit test cases, they run against a modified version of the android.jar file which does not contain any actual code because of which, when we try to invoke any method of an Android class from our test case, we get an exception. This is done to ensure that we test only our code and do not depend on some default behavior of the Android classes. We can also change this default behavior of throwing an exception to return zero or null values. However, we should avoid this as it could cause regressions in our test cases which are hard to debug.
We can substitute Android dependencies with mock objects. We can use Mockito for this to configure our mock objects to return some specific value when they are invoked.
Mockito Integration
To integrate Mockito in our Android apps, we first need to include the following dependencies in our app level build.gradle file.
Once we have added the required dependencies, we will create our test class in the directory module-name/src/test/java/, and add the @RunWith(MockitoJUnitRunner.class) annotation at the beginning of this class. This annotation tells the Mockito test runner to validate if the usage of the framework is correct and it also simplifies the mock object initializations.
We have to add @Mock annotation before the field declaration of any object we want to mock.
We can use the when() and thenReturn() methods to return a value when a particular condition is met in order to stub the behavior of any dependency.
Now, let’s have a look at a sample test class. The sample below checks that the method getHelloWorldString() of the class ClassUnderTest matches a given string.
How to Mock
We have 2 methods, mock() and spy() that can be used to create mock methods or fields.
Using the mock() method, we create complete mock or fake objects. The default behavior of mock methods is to do nothing.
Using the spy() method, we just spy or stub specific methods of a real object. As we use real objects in this case, if we do not stub the method, then the actual method is called.
We generally use mock() when we need complete mock objects, and use spy() when we need partial mock objects for which we need to mock or stub only certain methods.
Mocking Behaviour
Let’s look at how we can use Mockito methods to mock behaviour of the mock or spy objects we create.
when() :
It is used to configure simple return behavior for a mock or spy object.
doReturn() :
It is used when we want to return a specific value when calling a method on a mock object. The mocked method is called in case of both mock and spy objects. doReturn() can also be used with methods that don’t return any value.
thenReturn() :
It is used when we want to return a specific value when calling a method on a mock object. The mocked method is called in case of mock objects, and real method in case of spy objects. thenReturn() always expects a return type.
Now, let’s look at the common assertions we can use to assert that some condition is true:
assertXYZ() :
A set of assertion methods.
assertEquals(Object expectedValue, Object actualValue) :
Asserts that two objects are equal.
assertTrue(boolean condition) :
Asserts that a condition is true.
assertFalse(boolean condition) :
Asserts that a condition is false.
With the combination of the above mentioned methods and assertions, we can write test cases using the Mockito mocking framework.
Advantages & Disadvantages
Let’s have a look at the advantages and disadvantages of Mockito:
Advantages
- We can Mock any class or interface as per our need.
- It supports Test Spies, not just Mocks, thus it can be used for partial mocking as well.
Disadvantages
- Mockito cannot test static classes. So, if you’re using Mockito, it’s recommended to change static classes to Singletons.
- Mockito cannot be used to test a private method.
There are a few alternative mocking libraries like PowerMock, Robolectric and EasyMock available as well which can be used.