Mockito doesn’t give a Hangover – Java Unit Tests

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.

Tagged : / /

JUnit Annotations with Example

Introduction

Annotations were introduced in Junit4, which makes Java code more readable and simple. This is the big difference between Junit3 and Junit4 that Junit4 is annotation based.

JUnit5 is the next generation of JUnit. The goal is to create an up-to-date foundation for developer-side testing on the JVM. This includes focusing on Java 8 and above, as well as enabling many different styles of testing.With the knowledge of annotations in JUnit5, one can easily learn and implement a JUnit test.

JUnit offers integration with CI/CD tools such as Jenkins, Teamcity etc. to help you create a sturdy delivery pipeline.

Basic Java Annotations

So here are some basic JUnit annotation that are mostly used and required for unit testing :

  • @Test – This is the test method to run, public void
  • @BeforeClass – This annotation is used if you want to execute some statements before all the test cases for e.g. test connection must be executed before all the test cases., public static void
  • @AfterClass – This annotation can be used if you want to execute some statements after all test cases for e.g. Releasing resources after executing all test case, public static void
  • @Before – This annotation is used if you want to execute some statement such as preconditions before each test case, public void
  • @After – This annotation can be used if you want to execute some statements after each Test Case for e.g resetting variables, deleting temporary files ,variables, etc, public void

A simple example will help us to understand the working of JUnit annotations.

Java Class to be tested

We are going to use a simple example regarding Account balance where we want to perform our unit testing.

package com.thecodersstop.junit;
 
public class Account {
    private double bal;
 
    public Account(double bal) {
        this.bal = bal;
    }
 
    public double getBal() {
        return bal;
    }
 
    public void setBal(double bal) {
        this.bal = bal;
    }
 
    public void withdraw(double withdrawAmount) {
        this.bal = bal - withdrawAmount;
    }
 
    public void deposit(double depositAmount) {
        this.bal = bal + depositAmount;
    }
}

Junit Test Cases

Here we have our test cases for the Account java class. This test class includes all the basic annotations mentioned above.

package com.thecodersstop.junit;

import org.junit.*;
 
public class AccountTest extends Assert {
    private Account account;
    private static double bal;
 
    @BeforeClass
    public static void BeforeClass() {
		// Code executed before the first test method
        bal = 100;
        System.out.println("Before Class");
    }
 
    @Before
    public void beforeTest() throws Exception {
		// Code executed before each test
        account = new Account(bal);
    }
 
    @Test
    public void testCase1() {
        Assert.assertEquals("Test balance", account.getBal(), bal, 0);
        System.out.println("Test balance. Balance: " + account.getBal());
    }
 
    @Test
    public void testCase2() {
        account.deposit(10);
        Assert.assertEquals("Test deposit", account.getBal(), bal, 10);
        System.out.println("Test deposit. Balance: " + account.getBal());
    }
 
    @Test
    public void testCase3() {
        account.withdraw(30);
        Assert.assertEquals("Test withdraw", account.getBal(), bal, 30);
        System.out.println("Test withdraw. Balance: " + account.getBal());
    }
 
    @After
    public void afterTest() throws Exception {
		// Code executed after each test
        account = null;
        System.out.println("refresh");
    }
 
    @AfterClass
    public static void AfterClass() {
		// Code executed after the last test method
        balance = 0;
        System.out.println("After Class");
    }
}

Run the JUnit Test Cases

Here is the output of our test cases. As we can see, the sequence of the executed test methods, complies with what we described in the starting. This JUnit test is fully passed.

Before Class
Test balance. Balance: 100.0
refresh
Test deposit. Balance: 110.0
refresh
Test withdraw. Balance: 70.0
refresh
After Class

JUnit offers integrations with IDEs such as Eclipse, IntelliJ etc. so you could test run your code quickly and easily.

Execution Sequence of JUnit Annotations

Here is a basic process flowchart of JUnit annotations that will help you to understand the flow, step by step.

@Ignores – This annotation can be used if you want to ignore some statements during test execution for e.g. disabling some test cases during test execution.

I hope you have enjoyed this post and it helped you to understand the basics of JUnit annotations. Please like and share and feel free to comment if you have any suggestions or feedback.

Tagged : / /
%d bloggers like this: