Mockito doesn’t give a Hangover – Java Unit Tests

Mockito is a mocking framework. It is a Java-based library used to create simple and basic test APIs for performing unit testing of Java applications. It internally uses the Java Reflection API to generate mock objects for a specific interface. Mockito is in top 10 Java library across all libraries, not only the testing tools.

The following blog is based on an understanding of unit testing with the JUnit framework. In case your are not familiar with JUnit please check the following JUnit article.
Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors. We will cover some basic Mockito annotations that are mostly used by the developers.

How do I drink it?

To add mockito into the project, we can add the desired mockito version by any means i.e. maven, gradle or jar file.

pom.xml
<dependency>
	<groupId> org.mockito </groupId>
	<artifactId> mockito-core </artifactId>
	<version> 2.+ </version>
	<scope> test </scope>
</dependency>
build.gradle
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.23.4'
Verify interactions
import static org.mockito.Mockito.*;

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();
Stub method calls
// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);

// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");

// the following prints "first"
System.out.println(mockedList.get(0));

// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));

Mockito Annotations

Before we go further, let’s explore different ways to enable the use of annotations with Mockito tests.
The first option we have is to annotate the JUnit test with a MockitoJUnitRunner as in the following example:

@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationTest {
…
}

Alternatively, we can enable Mockito annotations programmatically as well, by invoking MockitoAnnotations.initMocks():

@Before
public void init() {
MockitoAnnotations.initMocks(this);
}

Lastly, we can use a MockitoJUnit.rule() as shown below:

public class MockitoInitWithMockitoJUnitRuleUnitTest {
 
    @Rule
    public MockitoRule initRule = MockitoJUnit.rule();
 
    ...
}

In this case, we must remember to make our rule public.

In our example, we are going to use the following annotations:-

  • @Mock – The @Mock annotation is used to create and inject mocked instances. We do not create real objects, rather ask mockito to create a mock for the class.
  • @InjectMocks – In mockito, we need to create the object of class to be tested and than insert it’s dependencies (mocked) to completely test the behavior. To do this, we use @InjectMocks annotation.

So, Let’s first create an interface called CalculatorService to provide mathematical functions.

CalculatorService.java
public interface CalculatorService {
   public double add(double input1, double input2);
   public double multiply(double input1, double input2);
}

Then, create a Java class to represent MathApplication.

MathApplication.java
public class MathApplication {
   private CalculatorService calcService;

   public void setCalculatorService(CalculatorService calcService){
      this.calcService = calcService;
   }

   public double add(double input1, double input2){
      return calcService.add(input1, input2);
   }

   public double multiply(double input1, double input2){
      return calcService.multiply(input1, input2);
   }
}

Let’s test the MathApplication class, by injecting in it a mock of calculatorService. Mock will be created by Mockito.

MathApplicationTest.java
import static org.mockito.Mockito.when;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

//RunWith attaches a runner with the test class to initialize the test data
@RunWith(MockitoJUnitRunner.class)
public class MathApplicationTest {
	
   //InjectMocks annotation is used to create and inject the mock object
   @InjectMocks 
   MathApplication mathApplication = new MathApplication();

   //Mock annotation is used to create the mock object to be injected
   @Mock
   CalculatorService calcService;

   @Test
   public void testAdd(){
      //add the behavior of calc service to add two numbers
      when(calcService.add(20.0,40.0)).thenReturn(60.0);
		
      //test the add functionality
      Assert.assertEquals(mathApplication.add(20.0, 40.0),60.0);
   }
}

 The test is successfully run using Mockito annotations.

The @Mock annotation is alternative to Mockito.mock(classToMock). They both achieve the same result. Using @Mock is usually considered “cleaner“, as we don’t fill up the tests with boilerplate assignments that all look the same.The other widely used are mentioned below:

  • @Spy – The @Spy annotation is used to create a real object and spy on that real object. A spy helps to call all the normal methods of the object while still tracking every interaction, just as we would with a mock.
  • @Captor – The @Captor annotation is used to create an ArgumentCaptor instance which is used to capture method argument values for further assertions.

I hope you have enjoyed this post and it helped you to understand the basics of mockito framework for unit testing in Java. Please like and share and feel free to comment if you have any suggestions or feedback.

Leave a Reply

%d bloggers like this: