Notes on Mockito Tutorial

Russell Bateman
22 August 2011
last update:

Table of Contents

Introduction
Glossary
static imports
Notes to put somewhere
Links
Example
StateBo.java
StateDao.java
BaseDao.java
State.java
StateBoTest.java
StateBoTest.java refined
Emerging methodology
Plan the test
Write the test

Introduction

I'm working through a tutorial on Mockito and some others to see if this is the technology we want to use in my group at work. If you have time to work through this, it will show you two important things:

  1. How to set up and use Mockito
  2. The workflow of test-driven development.

This is a very rough start that will take months to bear fruit.

Glossary

replay is the act of object scaffolding to produce and object.

strict mock semantics are when only the methods that are explicitly recorded are accepted as valid. Any method that's not expected causes an exception that fails the test and all the expected methods must be called if the object is to pass verification.

loose mock allows any method called during the replay state to be accepted and if there is not special handling set up for the method, a null or zero is returned. All the expected methods must be called if the object is to pass verification.

A stub is an object that is set up to feed the required inputs into the system under test.
when( ... ).theReturn( ... )

A mock is an object that is used to verify that the system under test interacts as expected with the object(s) it relies on.
verify( ...).methodXxx( ... )

happy-path test is a well defined test case using known input that executes without exception and produces expected output.

static imports

First, I loathe the use of wildcards in Java import statements. Here is the complete set for this tutorial:

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.anyString;

Notes to put somewhere

At Is there a difference between asking and telling, the inventor of Mockito says, "In practice: If I stub then it is verified for free, so I don't verify. If I verify then I don't care about the return value, so I don't stub. Either way, I don't repeat myself." This posting is not only interesting for the discussion by its author, but also for the discussion in the comments below.

Brice Dutheil says:

  1. Don't use try...catch in your test methods unless there is a good reason for that. Usually I code tests with @Test(expected = Exception.class) style. It has the benifit to remove the clutter.
  2.  
  3. @Test public testFillingDoesNotRemoveIfNotEnoughInStock(), test is redundant with the annotation, you can get rid of it, what we want is the test to be readable, almost like your native language, I now use the underscored style as the readability of the test intent is easier to read than with camel case. PLEASE NOTE that I ONLY recommand it for tests.
  4.  
  5. You don't need to assert what you just stubbed. i.e.: the hasInventory(anyString(), anyInt()), don't need to be asserted. This line is irrelevant: assertFalse( mockedWarehouse.hasInventory( TALISKER, 5 ) );

Equates and definitions

(Get to this table someday.)

stub when()

Useful Links


Example

This is from a ReST servlet I've written tests for. The architecture for this particular piece is fairly standard:

StateService (JAX-RS) -> StateBo (business logic) -> StateDao -> State (POJO/bean) -> database

I'm trying to write a unit test for StateBo. There's hardly any business logic in this piece; it was chosen as the simple case to get started on.

StateBo.java:

Here's the class to be placed under test...

package com.acme.user.bo;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.acme.user.entity.State;
import com.acme.user.entity.StateDao;

@Transactional
@Service( "stateBo" )
public class StateBo
{
    public static Logger log = Logger.getLogger( StateBo.class );

    @Autowired( required = true )
    private StateDao stateDao;

    public State create( State state )
    {
        return this.stateDao.create( state );
    }

    public List< State > findAll()
    {
        return this.stateDao.read();
    }

    public State findById( Integer id )
    {
        return this.stateDao.readById( id );
    }

    public List< State > findByPropertyAndValue( String propertyName, String propertyValue )
    {
        return this.stateDao.readByPropertyAndValue( propertyName, propertyValue );
    }

    public void update( State state )
    {
        this.stateDao.update( state );
    }

    public void delete( Integer id )
    {
        State state = findById( id );
        this.stateDao.delete( state );
    }

    /**
     * This injector is just for JUnit/Mockito tests which do not benefit from
     * proper Spring autowiring.
     */
    public void setDao( StateDao dao )
    {
        this.stateDao = dao;
    }
}
StateDao.java:

Here's the DAO class that we mock—since we don't actually wish to call down to Hibernate and the database.

package com.acme.user.entity;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Repository( "stateDao" )
public class StateDao extends BaseDao
{
    public static Logger log = Logger.getLogger( StateDao.class );

    @Transactional( readOnly = false, propagation = Propagation.MANDATORY )
    public State create( State state )
    {
        sessionFactory.getCurrentSession().save( state );
        return state;
    }

    @SuppressWarnings( "unchecked" )
    @Transactional( readOnly = true, propagation = Propagation.MANDATORY )
    public List< State > read()
    {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( State.class );
        criteria.isReadOnly();
        return criteria.list();
    }

    @Transactional( readOnly = true, propagation = Propagation.MANDATORY )
    public State readById( Integer id )
    {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( State.class );
        criteria.isReadOnly();
        criteria.add( Restrictions.idEq( id ) );
        return ( State ) criteria.uniqueResult();
    }

    @SuppressWarnings( "unchecked" )
    @Transactional( readOnly = true, propagation = Propagation.MANDATORY )
    public List< State > readByPropertyAndValue( String propertyName, String propertyValue )
    {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( State.class );
        criteria.add( Restrictions.ilike( propertyName, propertyValue, MatchMode.EXACT ) );
        return criteria.list();
    }

    @Transactional( readOnly = false, propagation = Propagation.MANDATORY )
    public void update( State state )
    {
        State stateToModify = readById( state.getId() );
        stateToModify.setCode( state.getCode() );
        stateToModify.setName( state.getName() );
        sessionFactory.getCurrentSession().update( stateToModify );
    }

    @Transactional( readOnly = false, propagation = Propagation.MANDATORY )
    public void delete( State state )
    {
        State stateToModify = readById( state.getId() );
        sessionFactory.getCurrentSession().delete( stateToModify );
    }
}
BaseDao.java:

(For completeness, here's the superclass for StateDao.)

package com.acme.user.entity;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class BaseDao
{
	@Autowired
	public SessionFactory sessionFactory;

	@Autowired
	public HibernateTemplate hibernateTemplate;

	public BaseDao()
	{
		super();
	}
}
State.java:

The POJO at the bottom representing the State table in the database.

package com.acme.user.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@Entity
@Table( name = "state" )
public class State implements Serializable
{
    private static final long serialVersionUID = 7690285996151938000L;

    private Integer id;
    private String country;
    private String code;
    private String name;

    public State() {}

    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE )
    @Column( name = "id", unique = true, updatable = false )
    public Integer getId() { return id; }
    public void setId( Integer id ) { this.id = id; }

    @Column( name = "country", nullable = false, length = 2 )
    public String getCountry() { return this.country; }
    public void setCountry( String country ) { this.country = country; }

    @Column( name = "code", nullable = false, length = 2 )
    public String getCode() { return this.code; }
    public void setCode( String code ) { this.code = code; }

    @Column( name = "name", nullable = false, length = 64 )
    public String getName() { return this.name; }
    public void setName( String name ) { this.name = name; }

    /**
     * This constructor is just for JUnit/Mockito tests. Providing it forces us to create
     * an explicit no-argument constructor without which this class fails when consumed by
     * the ReST servlet-proper.
     */
    public State( Integer id, String country, String code, String name )
    {
        this.id      = id;
        this.country = country;
        this.code    = code;
        this.name    = name;
    }
}
StateBoTest.java:

And now, this is the JUnit test mocking the DAO and testing the business logic.

package com.acme.user.bo;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Matchers.any;

import java.util.LinkedList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.acme.user.entity.State;
import com.acme.user.entity.StateDao;

public class StateBoTest
{
    private static final Integer ID_1    = new Integer( 1 );
    private static final Integer ID_2    = new Integer( 2 );
    private static final State   ALABAMA = new State( ID_1, "us", "al", "Alabama" );
    private static final State   ALASKA  = new State( ID_2, "us", "ak", "Fred" );
    private static final String  CODE    = "code";
    private static final String  AL_CODE = "al";

    private StateBo    bo;                 // the business logic
    private StateDao   dao;                // interface atop database

    @Before
    public void setup()
    {
        this.bo  = new StateBo();          // class under test
        this.dao = mock( StateDao.class ); // dependent class (mocked)
        this.bo.setDao( this.dao );        // every test needs this wiring
    }

    private final boolean checkStateResult( State control, State result )
    {
        assertEquals( control.getId(),      result.getId() );
        assertEquals( control.getCountry(), result.getCountry() );
        assertEquals( control.getCode(),    result.getCode() );
        assertEquals( control.getName(),    result.getName() );
        return true;
    }

    @Test
    public void testCreate()
    {
        // set up mocked result on create...
        when( this.dao.create( ALABAMA ) ).thenReturn( ALABAMA );

        // call the method we wish to test...
        State result = this.bo.create( ALABAMA );

        // verify the method was called...
        verify( this.dao ).create( result );

        // verify correct results returned...
        assertNotNull( result );
        assertTrue( checkStateResult( ALABAMA, result ) );
    }

    @Test
    public void testFindAll()
    {
        // squirrel-cage the database...
        List< State > all = new LinkedList< State >();
        all.add( ALABAMA );
        all.add( ALASKA );

        // return mocked result set on read...
        when( this.dao.read() ).thenReturn( all );

        // call the method we want to test...
        List< State > result = this.bo.findAll();

        // verify the method was called...
        verify( this.dao ).read();

        // verify correct number of results returned...
        assertEquals( 2, result.size() );

        // verify correct results returned...
        assertTrue( checkStateResult( ALABAMA, result.get( 0 ) ) );
        assertTrue( checkStateResult( ALASKA,  result.get( 1 ) ) );
    }

    @Test
    public void testFindById()
    {
        // return mocked result set on readById...
        when( this.dao.readById( 1 ) ).thenReturn( ALABAMA );

        // call the method we want to test...
        State result = this.bo.findById( 1 );

        // verify the method was called...
        verify( this.dao ).readById( 1 );

        // verify correct result returned...
        assertNotNull( result );
        assertTrue( checkStateResult( ALABAMA, result ) );
    }

    @Test
    public void testFindByPropertyAndValue()
    {
        // squirrel-cage the database...
        List< State > all = new LinkedList< State >();
        all.add( ALABAMA );
        all.add( ALASKA );

        // return mocked result set on readByPropertyAndValue...
        when( this.dao.readByPropertyAndValue( CODE, AL_CODE ) ).thenReturn( all );

        // call the method we want to test...
        List< State > result = this.bo.findByPropertyAndValue( CODE, AL_CODE );

        // verify the method was called...
        verify( this.dao ).readByPropertyAndValue( CODE, AL_CODE );

        // verify correct number of results returned...
        assertEquals( 2, result.size() );

        // verify correct results returned...
        assertTrue( checkStateResult( ALABAMA, result.get( 0 ) ) );
        assertTrue( checkStateResult( ALASKA,  result.get( 1 ) ) );
    }

    @Test
    public void testUpdate()
    {
        // stub mocked result on update...
        doNothing().doThrow( new IllegalStateException() )
            .when( this.dao ).update( any( State.class ) );

        // call the method we wish to test...
        this.bo.update( ALABAMA );

        // verify the method was called...
        verify( this.dao ).update( ALABAMA );

        // because there's no state to examine, we're done
    }

    @Test
    public void testDelete()
    {
        // stub mocked result on update...
        doNothing().doThrow( new IllegalStateException() )
            .when( this.dao ).delete( ALABAMA );

        /* Added complication for this method's test:
         * Set up mocked result for dao.readById() since bo.delete(), which
         * is under test, calls bo.findById() which itself calls dao.readById(),
         * but we haven't set up a mock result for that yet
         */
        when( this.dao.readById( ID_1 ) ).thenReturn( ALABAMA );

        // call the method we want to test...
        this.bo.delete( ID_1 );

        // verify the method was called...
        verify( this.dao ).delete( ALABAMA );

        // because there's no state to examine, we're done
    }
}
StateBoTest.java refined:

Support from the Mockito Googlegroup refines what's above. If a method is nothing more than a pass-through (which it is here owing to the rather zero amount of business logic in the StateBo example) you don't really care about the properties of a State. If the code begins to do other things (i.e.: more business logic) then you will document it in the test with identifiable scenarios.

Also, the test name should reflect the scenario it's testing.

Comparing the two (original above and Brice Dutheil's rewrite below) is instructive.

...
{
    ...
    @Test
    public void on_create_returns_same_instance()
    {
        when( this.dao.create( ALABAMA ) ).thenReturn( ALABAMA );

        State result = this.bo.create( ALABAMA );

        // no need for verify, otherwise the tests won't pass; the verification
        // in this context is implicit

        // there is no need to check the properties since StateBo is a pass-through
        assertSame( ALABAMA, result );

        // however if StateBo begins to do something, you might want to replace
        // that by an "assertStateProperties", but then you will give another
        // name to the test like:
        // "on_create_ensure_properties_do_have_<your expected values or meaning>"
    }

    @Test
    public void should_invoke_DAO_on_delete_by_id()
    {
        // delete scenario
        // Mockito mocks do nothing by default, no need to mock that

        // ok this is needed
        when( this.dao.readById( ID_1 ) ).thenReturn( ALABAMA );

        this.bo.delete( ID_1 );

        // ok, you do need to verify that the interaction happened
        verify( this.dao ).delete( ALABAMA );
    }

    @Test
    public void should_not_propate_on_second_delete_of_same_id()
    {
        // another delete scenario on successive delete of same id needed here
        // as part of the scenario
        doNothing().doThrow( new IllegalStateException() )
            .when( this.dao ).delete( ALABAMA );

        // this is still needed
        when( this.dao.readById( ID_1 ) ).thenReturn( ALABAMA );

        // here we're testing something else, i.e. that StateBo doesn't
        // propagate the exception on the second delete call: there is one more
        // call to delete than there are calls to doNothing() above which will
        // force the IllegalStateException() to occur*
        this.bo.delete( ID_1 );
        this.bo.delete( ID_1 );

        // verify of the interaction not needed, it was already in the previous test
    }
}

* this needs work to polish the concept.


Emerging methodology

Based on what I've learned writing short Mockito tests, many of which didn't work the first time, I've begun to create a sort of method for creating tests. I expect this to receive considerable modification over the near future.

Plan the test

  1. Determine which class is to be unit-tested. This is the "class under test".
  2.  
  3. Ascertain dependents of that class that must be mocked. This would include any that are too heavy like a database, web service, etc. Make a note of these.
  4.  
  5. Plan a new JUnit test with methods corresponding to at least the public ones in the class under test. Also, private methods with lots of important logic under them must be tested—individually if their functionality isn't massively and surely exposed by the public methods.
  6.  
  7. For each method, contemplate "stories" of what you would like to know succeeds and how it would behave under failure conditions. There should be English story names like
    on_create_returns_instance()
    should_invoke_DAO_on_delete_by_id()
    should_not_propagate_on_second_delete_of_same_id()
    defect_934632 (purists might scream at this)
    etc.

Write the test

  1. Create a new JUnit test class with all the planned methods.
  2.  
  3. Set up mocks for dependent functionality whose "real" execution cannot be tolerated for whatever inconvenience it would be.
  4.  
  5. Set up mocks for less obvious dependent functionality, discovered through inspection such as something the class method under test calls that calls something else that can't be allowed to execute.
  6.  
  7. Call the method under test (in the class under test).
  8.  
  9. Verify that the method under test was called including that it was called a specific number of times, at least a number of times, etc.
  10.  
  11. Examine new state or results returned comparing against what's expected.


Appendix: Random notes

How to use Mockito to test an abstract class when the class depends upon a strategy injected into its constructor?

// abstract class to be tested with mock instance...
abstract BaseClass
{
    // strategy gets mocked too
    protected BaseClass( Strategy strategy)
    {
        ...
    }
}

One answer is to create a local class that inherits from the abstract one and test it.

Strategy strategyMock = mock( Strategy.class);

when(....).thenReturn(...);

BaseClass baseMock = mock( BaseClass.class, CALLS_REAL_METHODS );
baseMock.getClass().getSuperclass().getDeclaredField( "_privateStrategy" ).set( baseMock, strategyMock );

// do unit tests with baseMock...