Introduction
Mockito is a popular mocking framework that is useful to test the written code. It enables to write the essential test cases for real-world projects and applications.
Unit Testing: It is a software testing technique to test the unit of a code that can be logically isolated in a system.
Unit: It is referred to as an individual functionality of a program.
Mocking: It is a process of creating mock or clone objects which act as dummy objects to the real objects. When we develop the applications, we develop them into layers.



Need for Mocking and Mockito Framework
Some of the points defined below illustrate the need for Mockito Framework:
- In case project is under developement, and we want test to the single component that is dependent on an another component which is incomplete. Then we can use mocking for writting the test cases.
- When we need to test the database operations wich are the working fast enough to meet the requirements. Then also we can mock the required objects to test the read/write operations using mocking.
Let’s see with an example of why we need the Mockito framework and how we can use it to test the written code:
Real Class
public class SampleClass {
public int doSummation(int [] input) {
int sum =0;
for(int val: input) {
sum += val;
}
return sum;
}
}
Test Class
@ExtendWith(MockitoExtension.class)
public class SampleClassTest {
@Test
public void doSummationWhenInputIsValid() {
SampleClass sampleObject = new SampleClass();
int actualOutput = sampleObject.doSummation(new int[] {10, 20, 30});
int expectedOutput = 60;
assertEquals(expectedOutput, actualOutput);
}
@Test
public void doSummationWhenInputIsEmpty() {
SampleClass sampleObject = new SampleClass();
int actualOutput = sampleObject.doSummation(new int[] {});
int expectedOutput = 0;
assertEquals(expectedOutput, actualOutput);
}
}
Some important annotations provided by Mockito Framework:
@Mock Annotation
This annotation helps to mock the real objects that reduce the repetition of mock objects. It enhances the readability of the test cases as the parameters. The @Mock annotation is available in the org.mockito package.
@Mock
ServiceClassName mockObjectName;
@Test
public void mocking() {
ArrayList mockArrayList = mock(ArrayList.class);
mockArrayList.get(0); // null
mockArrayList.size(); // 0
mockArrayList.add("Mock1");
mockArrayList.add("Mock2");
System.out.println(mockArrayList.size()); // 2
when(mockArrayList.size()).thenReturn(5);
System.out.println(mockArrayList.size()); // 5
}
@RunWith Annotation
This is a class-level annotation, allows to keep the test clean and to improve debugging. It also detects the unused stubs available in the test and initializes mocks annotated with @Mock annotation. The @RunWith annotation is available in the org.mockito.junit package.
@RunWith(MockitoJUnitRunner.class)
public class SeviceClassName {
}
@InjectMocks Annotation
This annotation marks a field or parameter on which the injection should be performed. It also allows short-hand mock and spy injections and minimizes the repetitive mocks and spy injection. The @InjectMocks annotation is available in the org.mockito package.
@InjectMocks
ServiceClassName mockObjectName;
@Captor Annotation
This annotation allows the creation of a field-level argument captor. And we can use Mockito’s verify() method to get the values passed when a method is called. The @Captor annotation is available in the org.mockito package.
@Captor
ArgumentCaptor<String> argumentCaptor;
@Spy Annotation
This annotation enables the creation of partially mock objects. That means it can wrap the field instances in a spy object. The @Spy annotation is available in the org.mockito package.
@Spy
ArrayList<String> spyArrayList;
@Test
public void spying() {
ArrayList spyArrayList = spy(ArrayList.class);
spyArrayList.add("Spy1");
System.out.println(spyArrayList.get(0)); // Spy1
System.out.println(spyArrayList.size()); // 1
spyArrayList.add("Spy2");
spyArrayList.add("Spy3");
System.out.println(spyArrayList.size()); // 3
when(spyArrayList.size()).thenReturn(10);
System.out.println(spyArrayList.size()); // 10
}
Example for bad practice v/s good practice
This is an example to showcase the difference between good and bad practices for writing test cases that enhance the readability of the test cases.
Bad Practice:
@Test
public void badTestExample() {
List<Product> products = new ArrayList<Product>();
products.add(new ProductImp(230, "Product123", ProductType.COSMETIC, new
AmountImp(new
BigDecimal("2.0"), Currency.INDIAN)));
products.add(new ProductImp(523, "Product245", ProductType.COSMETIC, new
AmountImp(new
BigDecimal("7.0"), Currency.INDIAN)));
Amount amt = clientDetails.getClientProductsSum(products);
assertEquals(Currency.INDIAN, amt.getCurrency);
assertEquals(new BigDecimal("9.0").INDIAN, amt.getValue);
}
Good Practice
@Test
public void goodTestExample() {
Amount[] amounts = {
new AmountImp(new BigDecimal("4.0"), Currency.INDIAN);
new AmountImp(new BigDecimal("7.0"), Currency.INDIAN);
};
Amount expectedAmount = new AmountImp(new BigDecimal("11.0", Currency.INDIAN));
List<Book> books = createBooksListWithAmount(amounts);
Amount actualAmount = clientDetails.getClientBooksSum(books);
assertEquals(actualAmount, expectedAmount);
}
Reference
For more detailed information about the Mockito framework, please click here.