Click here to Skip to main content
15,879,535 members
Articles / DevOps / Unit Testing

Mockito- a great mock framework for Java development.

Rate me:
Please Sign up or sign in to vote.
4.94/5 (30 votes)
27 Dec 2012CPOL9 min read 118.7K   147   15
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with clean & simple API.

Introduction

This artical will show some basic concepts of mocking framework, why we should use it and walkthrough a simple that applied Mockito in Java.

The concept of mocking  

Outside of the world of software development, the term “mock” means to imitate or to mimic. A “mock” can therefore be thought of as a stand-in, an imposter or as most commonly referred to as it pertains to softwaredevelopment, a fake.

Fakes are often used as stand-ins for dependencies of the class under test. 

Terms & Definitions  
Dependency – A dependency is when one class in an application depends upon another in order to perform its intended function. Dependencies are often stored in instance variables inside of the dependent class. 
Class Under Test – When writing unit tests, the term “unit” generally refers to a single class and specifically the class against which the tests are written. The class under test is therefore the application class that is being tested. 

Why Mock?  

When we learn to program, our objects are usually self contained. Any hello world has no dependencies on outside classes (System.out aside) and neither do many of the other classes we write in the process of learning a language. However, in the real world, software has dependencies. We have action classes that depend on services and services that depend on data access objects (DAOs) and the list goes on.

                                              

The idea of unit testing is that we want to test our code without testing the dependencies. This test allows you to verify that the code being tested works, regardless of it's dependencies. The theory is that if the code I write works as designed and my dependencies work as designed, then they should work together as designed. The code below would be an example of this:  

Java
import java.util.ArrayList;
public class Counter {
     public Counter() {
     }
     public int count(ArrayList items) {
          int results = 0;
          for(Object curItem : items) {
               results ++;
          }
          return results;
     }
} 

I know the above example is about as simple as you get, but it illustrates the point. If you wanted to test the method count, you would write at test that addressed how the count method works. You aren't trying to test that ArrayList works because you assume that it has been tested and works as designed. Your only goal is to test your use of ArrayList.  

The concept behind mock objects is that we want to create an object that will take the place of the real object. This mock object will expect a certain method to be called with certain parameters and when that happens, it will return an expected result. 

What are the key mocking concepts?

When it comes to mocking, there are only 3 things you really need to worry about; stubbing, setting expectations and verifying. Some unit test scenarios don’t involve any of these, others involve only stubbing and others involve setting expectations and verifying.

Stubbing 

Stubbing is the process of telling your fake how to behave when it is interacted with. You can generally stub public properties (those with getters and/or setters) and public functions.

When it comes to stubbing functions, you have a lot of choices typically. You may wish to return a specific value, throw an error or dispatch an event. Further, you may wish to indicate that the function behave differently depending upon how it is invoked (i.e. by matching the types or values of the parameters passed to the function).

If this sounds like a lot of work, it can be, but it generally isn’t. One great feature of many of the mocking frameworks is that you need not stub void functions. Nor do you have to stub any functions that are not invoked or properties that are not consulted during the execution of your tests.

Setting expectations 

One of the key features of a fake is the ability to tell the fake what you expect when your test runs. For example, you may expect that a specific function be invoked exactly 3 times. You may expect that it never be invoked. You may expect that it be invoked at least twice, but not more than 5 times. You may expect that it be invoked with specific types of arguments or specific values or any combination of the above. The possibilities are endless. 

Setting expectations is the process of telling your fake what you expect to happen to it. Remember that since it’s a fake, nothing actually happens. But, your class under test is none the wiser. From its perspective, it invoked the function and expects that it did whatever it was supposed to do. 

For what it’s worth, most mocking frameworks let you create mocks of interfaces or public classes. You are not limited to having to mock only interfaces. 

Verifying 

Setting expectations and verification go hand in hand. Setting expectations is done prior to invoking the function(s) on the class under test. Verification is done after. So, first you set expectations, then you verify that your expectations were met.

From a unit testing perspective, if your expectations were not met, the unit test fails. For example, if you set the expectation that the ILoginService.login function should be invoked exactly once with a specific username and password, but it was never invoked during the execution of your test, then the fake would not verify and the test should fail. 

What are the benefits of mocking? 

   You can create tests in advance; TDD  

        This one is one of the stronger benefits. If you create a Mock you can write Service Tests before the service is created, giving you the ability to add the tests to your automation environment in the development process. In other words, Service Mocking gives you the ability to use Test Driven Development. 

   Teams can work in parallel 

        This is similar to the above; create tests for code that does not exist. But the previous point was for the developer who writes tests, this one is for the Testing Team. How does the team start creating tests when you don’t have anything to test? Mock it and write tests against the Mock! This means it’s actually possible for the QA Team to have a full suite of tests ready when a service is ready to be tested; we don’t have downtimes when one team waits for the other to finish. This makes the financial argument for mocking particularly strong. 

   You can create proof of concepts or demos. 

        Since Mocks can (done levelheadedly) be very cost efficient to make, Mocks can be used to create a proof of concept, as a wireframe, or as a demo for something you’re considering building. This is very powerful and gives a good ground for making decisions about both whether to go ahead with a development project or not, but most importantly for actual design decisions. 

  You can write test for resource not accessible 

      This is one of those benefits that doesn’t fall into the actual benefits category, but rather works as a life saver. Ever wanted to test or use a service, only to get told that the service is behind a firewall and that that firewall can’t be opened for you or that you’re an authorized to use it? When you do, a MockService placed in an accessible place, including on your local computer, is a life saver. 

  Mock can be delivered to the customer 

      There are cases where there are reasons why you can’t allow access to your test systems for external sources, like partners or customers. These reasons can be access security, sensitivity of information, or just the fact that the test environment might not be accessible 24/7. In these cases; how do you provide a test system for your partner or customer to start development or test against? An easy solution is to provide a mock, either from your network or from your customers own network. A soapUI mock is extremely easy to deploy, it can either run in soapUI or exported as a .WAR file and placed in your java server of choice. 

  You can isolate systems 

      Sometimes you would like to test a part of your system without having other system parts affect it. This because the other systems will add noise to the test data and make it harder to make good conclusions from the data collected. Using mocks you can remove all dependencies mocking all systems except the one system you need to pinpoint in your tests. When doing mocks for isolation these mocks can be made extremely simple but reliable, fast, and predictable. This gives you a test environment where you have removed all stochastic behavior, have repeatable patterns and can monitor specific systems well. 

Mockito framework

Mockito is an open source testing framework for Java released under the MIT License. 
Mockito distinguishes itself from other mocking frameworks by allowing developers to verify the behavior of the system under test (SUT) without establishing expectations beforehand.[4] One of the criticisms of mock objects is that there is a tighter coupling of the test code to the system under test.[5] Since Mockito attempts to eliminate the expect-run-verify pattern[6] by removing the specification of expectations, the coupling is reduced or minimized. The result of this distinguishing feature is simpler test code that should be easier to read and modify. 

You can verify interactions:  

Java
// mock creation
List mockedList = mock(List.class);
<span class="Apple-tab-span" style="white-space: pre;">	
</span>// using mock object
mockedList.add("one");
mockedList.clear();
// selective and explicit vertification
verify(mockedList).add("one");
verify(mockedList).clear();   

Or stub method calls

Java
// you can mock concrete class, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
<span class="Apple-tab-span" style="white-space: pre;">	
</span>// stubbing - before execution
when(mockedList.get(0)).thenReturn("first");
<span class="Apple-tab-span" style="white-space: pre;">	
</span>// following prints "first"
System.out.println(mockedList.get(0));
<span class="Apple-tab-span" style="white-space: pre;">	
</span>// following prints "null" because get(999) was not stubbed.
System.out.println(mockedList.get(999)); 

A simple example Java code used Mockito 


                                                            Without Mock framework

 


                                                           With Mockito framework 

Step 1:  Create a Maven project in Eclipse 

 Define the pom.xml as below : 

XML
<?xml version="1.0" encoding="UTF-8"?>
<pre><project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>vn.com.phatbeo.ut.mockito.demo</groupId>
  <artifactId>demoMockito</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>demoMockito</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.1</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      </plugins>
  </build>
  
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
</project> 

Step 2:  Add java source code  

Class Person.java

Java
 package vn.com.enclave.phatbeo.ut.mockito.demo;
/** 
 * @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>
 *  
 */ 
public class Person
{
    private final Integer personID;
    private final String personName;
    public Person( Integer personID, String personName )
    {
        this.personID = personID;
        this.personName = personName;
    }
    public Integer getPersonID()
    {
        return personID;
    }
    public String getPersonName()
    {
        return personName;
    }
} 

 Interface PersonDAO.java 

Java
package vn.com.enclave.phatbeo.ut.mockito.demo;
/**
 * @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>
 * 
 */
public interface PersonDao
{
    public Person fetchPerson( Integer personID );
    public void update( Person person );
} 

 Class PersonService.java 

 package vn.com.enclave.phatbeo.ut.mockito.demo;
/**
 * @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>
 * 
 */
public class PersonService
{
    private final PersonDao personDao;
    public PersonService( PersonDao personDao )
    {
        this.personDao = personDao;
    }
    public boolean update( Integer personId, String name )
    {
        Person person = personDao.fetchPerson( personId );
        if( person != null )
        {
            Person updatedPerson = new Person( person.getPersonID(), name );
            personDao.update( updatedPerson );
            return true;
        }
        else
        {
            return false;
        }
    }
} 

 

Step 3:  Added unit-test class.  

Then, jump to write unit test cases for class PersonService.java 

In assumption, class PersionServiceTest.java is as below:

Java
package vn.com.enclave.phatbeo.ut.mockito.demo.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/**
 * @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>
 * 
 */
public class PersonServiceTest
{
    @Mock
    private PersonDao personDAO;
    private PersonService personService;
    @Before
    public void setUp()
        throws Exception
    {
        MockitoAnnotations.initMocks( this );
        personService = new PersonService( personDAO );
    }
    @Test
    public void shouldUpdatePersonName()
    {
        Person person = new Person( 1, "Phillip" );
        when( personDAO.fetchPerson( 1 ) ).thenReturn( person );
        boolean updated = personService.update( 1, "David" );
        assertTrue( updated );
        verify( personDAO ).fetchPerson( 1 );
        ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass( Person.class );
        verify( personDAO ).update( personCaptor.capture() );
        Person updatedPerson = personCaptor.getValue();
        assertEquals( "David", updatedPerson.getPersonName() );
        // asserts that during the test, there are no other calls to the mock object.
        verifyNoMoreInteractions( personDAO );
    }
    @Test
    public void shouldNotUpdateIfPersonNotFound()
    {
        when( personDAO.fetchPerson( 1 ) ).thenReturn( null );
        boolean updated = personService.update( 1, "David" );
        assertFalse( updated );
        verify( personDAO ).fetchPerson( 1 );
        verifyZeroInteractions( personDAO );
        verifyNoMoreInteractions( personDAO );
    }
} 

Points of Interest 

 + What's Mock framework in overview.

 + Why we use Mockito in testing in Java development. 

References

http://java.dzone.com/articles/the-concept-mocking  

http://en.wikipedia.org/wiki/Mockito 

http://code.google.com/p/mockito/ 

History

First release on Dec 26, 2012

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
GeneralMy vote of 5 Pin
WebMaster29-Dec-12 21:23
WebMaster29-Dec-12 21:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.