Home » Core Java » Mockito » Test-Driven Development With Mockito

About Mohammad Meraj Zia

Mohammad Meraj Zia
I did my Engineering in Information Technology from IET, Lucknow, India. Currently doing MSc in Information Technology from Derby University. I have worked in Java/J2EE domain for the last 10 years. Have good understanding of Payment and Finance domains.

Test-Driven Development With Mockito

In this example we will learn how to do a Test Driven Development (TDD) using Mockito. A unit test should test a class in isolation. Side effects from other classes or the system should be eliminated if possible. Mockito lets you write beautiful tests with a clean & simple API. Tools and technologies used in this example are Java 1.8, Eclipse Luna 4.4.2

1. Introduction

Mockito is a popular mocking framework which can be used in conjunction with JUnit. Mockito allows us to create and configure mock objects. Using Mockito simplifies the development of tests for classes with external dependencies significantly. We can create the mock objects manually or we can use the mocking framewors like Mockito, EasyMock. jMock etc. Mock frameworks allow us to create mock objects at runtime and define their behavior. The classical example for a mock object is a data provider. In production a real database is used, but for testing a mock object simulates the database and ensures that the test conditions are always the same.

Want to master Mockito?

Subscribe to our newsletter and download the Mockito Programming Cookbook right now!

In order to get you prepared for your Mockito development needs, we have compiled numerous recipes to help you kick-start your projects. Besides reading them online you may download the eBook in PDF format!

 

2. Test Driven Development

Test-Driven Development (TDD) is an evolutionary approach to development. It offers test-first development where the production code is written only to satisfy a test. TDD is the new way of programming. Here the rule is very simple; it is as follows:

  1. Write a test to add a new capability (automate tests).
  2. Write code only to satisfy tests.
  3. Re-run the tests—if any test is broken, revert the change.
  4. Refactor and make sure all tests are green.
  5. Continue with step 1.

3. Creating a project

Below are the steps required to create the project.

  • Open Eclipse. Go to File=>New=>Java Project. In the ‘Project name’ enter ‘TDDMockito’.
Figure 1. Create Java Project

Figure 1. Create Java Project

  • Eclipse will create a ‘src’ folder. Right click on the ‘src’ folder and choose New=>Package. In the ‘Name’ text-box enter ‘com.javacodegeeks’. Click ‘Finish’.
Figure 2. New Java Package

Figure 2. New Java Package

  • Right click on the package and choose New=>Class. Give the class name and click ‘Finish’. Eclipse will create a default class with the given name.

3.1 Dependencies

For this example we need the junit and mockito jars. These jars can be downloaded from Maven repository. We are using ‘junit-4.12.jar’ and ‘mockito-all-1.10.19.jar’. There are the latests (non-beta) versions available as per now. To add these jars in the classpath right click on the project and choose Build Path=>Configure Build Path. The click on the ‘Add External JARs’ button on the right hand side. Then go to the location where you have downloaded these jars. Then click ok.

4. Test first

Let’s say we want to build a tool for Report generation. Please note that this is a very simple example of showing how to use mockito for TDD. It does not focus on developing a full report generation tool.

For this we will need three classes. The first one is the interface which will define the API to generate the report. The second one is the report entity itself and the third one is the service class. First we will start with writing the test.

We will inject the service class by using @InjectMocks.

@InjectMocks private ReportGeneratorService reportGeneratorService;

@InjectMocks mark a field on which injection should be performed. It allows shorthand mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won’t report failure i.e. you will have to provide dependencies yourself.

Constructor injection: the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. If the object is successfully created with the constructor, then Mockito won’t try the other strategies. Mockito has decided  not to corrupt an object if it has a parametered constructor. If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won’t happen. In these cases, you will have to satisfy dependencies yourself.

Property setter injection: mocks will first be resolved by type (if a single type matches injection will happen regardless of the name), then, if there are several property of the same type, by the match of the property name and the mock name. If you have properties with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.

Field injection: mocks will first be resolved by type (if a single type matches injection will happen regardless of the name), then, if there is several property of the same type, by the match of the field name and the mock name. If you have fields with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.

Now we will mock the interface using @Mock annotation:

@Mock private IReportGenerator reportGenerator;

Now we will define the argument captor on report entity:

@Captor private ArgumentCaptor<ReportEntity> reportCaptor;

The ArgumentCaptor class is used to capture argument values for further assertions. Mockito verifies argument values in natural java style: by using an equals() method. This is also the recommended way of matching arguments because it makes tests clean & simple. In some situations though, it is helpful to assert on certain arguments after the actual verification.

Now we will define a setup method which we will annotate with @Before. This we will use to initialize the mocks.

MockitoAnnotations.initMocks(this);

initMocks() initializes objects annotated with Mockito annotations for given test class.

In the test method we will call the generateReport() method of the ReportGeneratorService class passing the required parameters:

reportGeneratorService.generateReport(startDate.getTime(), endDate.getTime(), reportContent.getBytes());

Below is the snippet of the whole test class:

ReportGeneratorServiceTest.java

package com.javacodegeeks;

import static org.junit.Assert.assertEquals;

import java.util.Calendar;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class ReportGeneratorServiceTest {

  @InjectMocks private ReportGeneratorService reportGeneratorService;
  @Mock private IReportGenerator reportGenerator;
  @Captor private ArgumentCaptor<ReportEntity> reportCaptor;

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

  @SuppressWarnings("deprecation")
  @Test
  public void test() {
    Calendar startDate = Calendar.getInstance();
    startDate.set(2016, 11, 25);
    Calendar endDate = Calendar.getInstance();
    endDate.set(9999, 12, 31);
    String reportContent = "Report Content";
    reportGeneratorService.generateReport(startDate.getTime(), endDate.getTime(), reportContent.getBytes());

    Mockito.verify(reportGenerator).generateReport(reportCaptor.capture());

    ReportEntity report = reportCaptor.getValue();

    assertEquals(116, report.getStartDate().getYear());
    assertEquals(11, report.getStartDate().getMonth());
    assertEquals(25, report.getStartDate().getDate());

    assertEquals(8100, report.getEndDate().getYear());
    assertEquals(0, report.getEndDate().getMonth());
    assertEquals(31, report.getEndDate().getDate());

    assertEquals("Report Content", new String(report.getContent()));
  }

}

The test class will not compile as the required classes are missing here. Don’t worry as this is how TDD works. First we write the test then we build our classes to satisfy the test requirements.

Now lets start adding the classes. First we will add the interface. This is the same interface which we mocked in our test class. The service class will have reference to this interface.

IReportGenerator.java

package com.javacodegeeks;

/**
* Interface for generating reports.
* @author Meraj
*/
public interface IReportGenerator {

  /**
  * Generate report.
  * @param report Report entity.
  */
  void generateReport(ReportEntity report);

}

Please note that this interface will also not compile as the ReportEntity class is still missing. Now lets add the entity class. This class represents the domain object in our design.

ReportEntity.java

package com.javacodegeeks;

import java.util.Date;

/**
* Report entity.
* @author Meraj
*/
public class ReportEntity {

  private Long reportId;
  private Date startDate;
  private Date endDate;
  private byte[] content;

  public Long getReportId() {
    return reportId;
  }

  public void setReportId(Long reportId) {
    this.reportId = reportId;
  }

  public Date getStartDate() {
    return startDate;
  }

  public void setStartDate(Date startDate) {
    this.startDate = startDate;
  }

  public Date getEndDate() {
    return endDate;
  }

  public void setEndDate(Date endDate) {
    this.endDate = endDate;
  }

  public byte[] getContent() {
    return content;
  }

  public void setContent(byte[] content) {
    this.content = content;
  }
}

Now lets add the service class:

ReportGeneratorService.java

package com.javacodegeeks;

import java.util.Date;

/**
* Service class for generating report.
* @author Meraj
*/
public class ReportGeneratorService {

  private IReportGenerator reportGenerator;

  /**
  * Generate report.
  * @param startDate start date
  * @param endDate end date
  * @param content report content
  */
  public void generateReport(Date startDate, Date endDate, byte[] content) {
    ReportEntity report = new ReportEntity();
    report.setContent(content);
    report.setStartDate(startDate);
    report.setEndDate(endDate);
    reportGenerator.generateReport(report);
  }

}

Now all the classes will compile and we can run our test class.

5. Download the source file

This was an example of using Mockito to do Test Driven Development.

Download
You can download the full source code of this example here: TDD Mockito

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

Leave a Reply

Be the First to Comment!

avatar
  Subscribe  
Notify of
Want to take your Java skills to the next level?
Grab our programming books for FREE!
Here are some of the eBooks you will get:
  • Spring Interview QnA
  • Multithreading & Concurrency QnA
  • JPA Minibook
  • JVM Troubleshooting Guide
  • Advanced Java
  • Java Interview QnA
  • Java Design Patterns
The Spring Framework Cookbook
  • Learn the best practices of the Spring Framework
  • Build simple, portable, fast and flexible JVM-based systems and applications
  • Explore specific projects like Boot and Batch
The Selenium Programming Cookbook
  • Kick-start your own projects using this testing framework for web applications
  • Learn JUnit integration and Standalone Server functionality
  • Find out the most popular Interview Questions about the Selenium Framework
The Spring Data Programming Cookbook
  • Learn how to use data access technologies and cloud-based data services
  • Set up the environment and create a basic project
  • Learn how to handle the various modules (e.g. JPA, MongoDB, Redis etc.)
The Mockito Programming Cookbook
  • Kick-start your own web projects using this open source testing framework
  • Write simple test cases using the Mockito Framework
  • Learn how to integrate with JUnit, Maven and other frameworks
The JUnit Programming Cookbook
  • Learn basic usage and configuration of JUnit
  • Create multithreaded tests
  • Learn how to integrate with other testing frameworks
The JSF 2.0 Programming Cookbook
  • Build component-based user interfaces for web applications
  • Set up the environment and create a basic project
  • Learn Internationalization and Facelets Templates
The Amazon S3 Tutorial
  • Develop your own Amazon S3 based applications
  • Learn API usage and pricing
  • Get your own projects up and running in minimum time
Java Design Patterns
  • Learn how Design Patterns are implemented and utilized in Java
  • Understand the reasons why patterns are so important
  • Learn when and how to apply each one of them
Java Concurrency Essentials
  • Dive into the magic of concurrency
  • Learn about concepts like atomicity, synchronization and thread safety
  • Learn about testing concurrent applications
The IntelliJ IDEA Handbook
  • Kick-start your own programming projects using IntelliJ IDEA
  • Learn how to setup and install plugins
  • Create UIs with this Java integrated development environment
The Git Tutorial
  • Learn why Git differs from other version control systems
  • Explore Git's usage and best practises
  • Learn branching strategies
The Eclipse IDE Handbook
  • Explore the most widely used Java IDE
  • Learn how to setup and install plugins
  • Built your own projects up and running in minimum time
The Docker Containerization Cookbook
  • Explore the world’s leading software containerization platform
  • Learn how to wrap a piece of software in a complete filesystem
  • Learn how to use DNS and various commands
Developing Modern Applications With Scala
  • Develop modern Scala applications
  • Build SBT and reactive applications
  • Learn about testing and database access
The Apache Tomcat Cookbook
  • Explore Apache Tomcat open-source web server
  • Learn about installation, configuration, logging and clustering
  • Kick-start your own web projects using Apache Tomcat
The Apache Maven Cookbook
  • Explore the Apache Maven build automation tool
  • Learn about Maven's project structure and configuration
  • Learn about Maven's dependency management and plug-ins
The Apache Hadoop Cookbook
  • Explore the Apache Hadoop open-source software framework
  • Learn distributed caching and streaming
  • Kick-start your own web projects using Apache Hadoop
The Android Programming Cookbook
  • Explore the Android mobile operating system
  • Learn about services and page views
  • Learn about Google Maps and Bluetooth functionality
The Elasticsearch Tutorial
  • Explore the Elasticsearch search engine
  • Develop your own Elasticsearch based applications
  • Learn operations, Java API Integration and reporting
Amazon DynamoDB Tutorial
  • Develop your own Amazon DynamoDB based applications
  • Learn DynamoDB Concepts and Best Practices
  • Get your own projects up and running in minimum time
Java NIO Programming Cookbook
  • Learn features for intensive I/O operations
  • Follow a series of tutorials on Java NIO examples
  • Get knowledge on Java Nio Socket and Asynchronous Channels
JBoss Drools Cookbook
  • Explore Drools business rule management system
  • Follow a series of tutorials on Drools examples
  • Get knowledge on business rules for a shopping domain model
Vaadin Programming Cookbook
  • Explore Vaadin web framework for rich Internet applications
  • Learn the Architecture and Best Practices
  • Get knowledge on Data Binding and Custom Components
Groovy Programming Cookbook
  • Explore Apache Groovy object-oriented programming language
  • Create sample applications and explore interview questions
  • Get knowledge on Callback functionality and various widgets
GWT Programming Cookbook
  • Explore the open source Google Web Toolkit
  • Create sample applications and explore interview questions
  • Create and maintain complex JavaScript front-end applications in Java
Amazon Elastic Beanstalk Tutorial
  • Develop your own Amazon Elastic Beanstalk based applications
  • Learn Java Integration and Command Line Interfacing
  • Get your own projects up and running in minimum time
Want to take your Java skills to the next level?
Grab our programming books for FREE!
Here are some of the eBooks you will get:
  • Spring Interview QnA
  • Multithreading & Concurrency QnA
  • JPA Minibook
  • JVM Troubleshooting Guide
  • Advanced Java
  • Java Interview QnA
  • Java Design Patterns
Apache ActiveMQ Cookbook
  • Explore Apache ActiveMQ Best Practices
  • Learn ActiveMQ Load Balancing and File Transfer
  • Develop your own Apache ActiveMQ projects