Mockito ReST Notes

Very random; I haven't been taking too many Mockito notes though I work very intensively with it.


Frequently used cribs...

Imports

Mockito imports Mockito static imports
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.mockito.ArgumentCaptor;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyObject;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.AdditionalAnswers.returnsSecondArg;

Various Mockito sample statements

Highlighted are lines with specifically Mockito constructs.

@Test
public void testSendWithStringProperties() throws Exception
{
  AmazonSQSClient awsClient = Mockito.mock( AmazonSQSClient.class );
  SqsOperations sqsOperations = setup();

  // this makes send() encode properties with the message body...
  Message message = setupMessageWithStringProperties();
  message.setId( null );

  when( awsClient.sendMessage( any( SendMessageRequest.class ) ) ).thenReturn( sendMessageResult( message ) );

  ArgumentCaptor< SendMessageRequest > argument = ArgumentCaptor.forClass( SendMessageRequest.class );

  String messageId = sqsOperations.send( message );
  assertNotNull( messageId );

  verify( awsClient ).sendMessage( argument.capture() );

  String url = argument.getValue().getQueueUrl();
  String body = argument.getValue().getMessageBody();

  // now verify what was passed as SendMessageRequest, but...
  assertEquals( url, AWS_QUEUE_URL );
  // ...the message body has one or more encoded properties inside, so check that too
  assertEquals( body, BODY_SPROPS );
}

Use of Mockito.mock() to create a mock. Use of when(), ArgumentCaptor and verify().

@Test
public void testMarkInProgress()
{
  // mock out the SUT's guts with a messenger and (minimal) behavior of returning our fake message...
  messenger = Mockito.mock( Messenger.class );
  when( messenger.createMessage()).thenReturn( new MessageImpl() );
  doAnswer( new Answer< Void >()
  {
    public Void answer( InvocationOnMock invocation )
    {
      Object[] args = invocation.getArguments();
      return null;
    }
  } ).when( messenger ).send( any( QueueId.class ), any( Message.class ) );

  ArgumentCaptor< Message > argument = ArgumentCaptor.forClass( Message.class );

  fixture.markInProgress( osId, Type.FHID );

  verify( messenger ).send(any( QueueId.class ), argument.capture() );
  assertNotNull( argument.getValue().getProperty( FHID_PROPERTY ) );
}
@Test
public void testMarkInProgress()
{
  // 1. Mock out the fixture's guts with a messenger
  messenger = Mockito.mock( Messenger.class );

  // 1bis. Make createMessage() do what it normally would
  when( messenger.createMessage() ).thenReturn( new MessageImpl() );

  // 2. Set up a fixture for the class under test
  fixture = new ReservationMessageFactoryImpl();
  fixture.setConfigSection( "pubResvMessage" );
  PropertySet ps = PropertyManager.getPropertySet( fixture.getConfigSection() );
  ps.setVolatileProperty( "queues", "ACME;ACMETESTS" );
  fixture.setMsgStore( messenger );

  // 2bis. We'll need two queues (remember that)
  List<String > queueList = new ArrayList<>( 1 );
  queueList.add( "ACME_RESV" );
  fixture.setQueues( queueList );
  fixture.init();

  // 3. Set to capture the message argument passed to Messenger.send()
  ArgumentCaptor< Message > argument = ArgumentCaptor.forClass( Message.class );

  // 4. Call the fixture
  fixture.markInProgress( osId, ACME_QUEUE );

  // 5. Verify that send() was called (twice, right?) and gather second argument
  verify( messenger, times( 2 ) ).send( any( QueueId.class ), argument.capture() );

  // 6. Assert that the fhId was in the message, which we have because it was captured
  // 6bis. Assert other stuff about the message generally
  Message result = argument.getValue();
  assertNotNull( result.getProperty( FHID_PROPERTY ) );
  assertTrue( result.getProperty( FHID_PROPERTY ).equals( DEFAULT_FHID ) );
  assertNotNull( result.getProperty( ACME_TYPE_PROPERTY ) );
  assertTrue( result.getProperty( ACME_TYPE_PROPERTY ).equals( ACME_QUEUE.getValue() ) );
  assertTrue( result.getPriority() == Message.Q_PRIORITY_MEDIUM );
  assertTrue( result.getMessageType().equals( MSG_TYPE ) );
}

Use of annotation @Mock and MockitoAnnotations.initMocks(this) to create a mock. Use of BDD given and returnsFirstArg().

public class TestMarkInProgressMsgImpl
{
  ...
  private Message message = setupMessage();

  private MarkInProgressMsgImpl fixture;

  @Mock private TransactionTypeRecorder    transactionTypeRecorder;
  @Mock private ReservationMessageFactory  reservationMessageFactory;
  @Mock private PrintingEventResponder     printingEventResponder;
  @Mock private SensitiveDataMessageHelper sensitiveDataMessageHelper;
  @Mock private HeartBeatMonitor           heartBeatMonitor;

  @BeforeMethod
  public void setUp() throws Exception
  {
    MockitoAnnotations.initMocks( this );
    fixture = new MarkInProgressMsgImpl();

    transactionTypeRecorder.setTransactionType( TransactionType.RESERVATION );
    fixture.setTransactionTypeRecorder( transactionTypeRecorder );
    fixture.setPrintingEventResponder( printingEventResponder );
    fixture.setMessageFactory( reservationMessageFactory );

    when( reservationMessageFactory.getInProgressPrimaryPrincipal( any( Message.class ) ) ).thenReturn( primaryPrincipalFtId.getIdAsServiceApiString() );
    when( reservationMessageFactory.getInProgressType( any( Message.class ) ) ).thenReturn(Type.CEILING );
    when( reservationMessageFactory.getInProgressChief( any( Message.class ) ) ).thenReturn( CHIEF_FTID );
    when( reservationMessageFactory.getInProgressAssistant( any( Message.class ) ) ).thenReturn( ASSISTANT_FTID );
    when( reservationMessageFactory.getInProgressCoworker( any( Message.class ) ) ).thenReturn( COWORKER_FTID );
    when( reservationMessageFactory.getInProgressFhid( any( Message.class ) ) ).thenReturn( FHID );
    given( sensitiveDataMessageHelper.embedPersonInformationInMessage( any( Message.class ) ) ).will( returnsFirstArg() );
  }

And now, the "void" stub/mock: the doAnswer() wiggle above is only necessary if I want to extract a value from the mess down inside, which isn't always the case. If you just want to set up a void method in a mocked class, and want it to do nothing when called (that's pretty much what it will do anyway, but here we'll be explicit about it), then use doNothing():

    doNothing().when(messenger).acknowledgeMessage(queueId, MESSAGE_ID);

The Answer construct...

This is the old way to squirrel-cage create() in Mockito, pre 1.9.5.rc1.

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.BDDMockito.given;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.bson.types.ObjectId;

...

@Test
public void testCreate_oldway()
{
    Answer< Account > answer = new Answer< Account >()
    {
        public Account answer( InvocationOnMock invocation ) throws Throwable
        {
            Object[] args = invocation.getArguments();
            Account account = ( Account ) args[ 0 ];
            account.setOid( JACK_OID );
            account.setIdentityoid( JACK_ID_OID );
            account.setPassword( JACK_PASS );
            account.setPartneroid( ACME_OID );
            return account;
        }
    };
    when( dao.create( any( Account.class ) ) ).thenAnswer( answer );

    when( partnerDao.readByOid( ACME_OID ) ).thenReturn( ACME );
    when( identityDao.readByOid( JACK_ID_OID ) ).thenReturn( JACK_ID );
    when( dao.readByIdentityAndPartneroids( any( ObjectId.class ), any( ObjectId.class ) ) ).thenReturn( JACK );

    AccountDto JACK_DTO = JACK.dto();
    JACK_DTO.setOid( JACK_OID );
    JACK_DTO.setPassword( JACK_PASS );      // (have to inject this artificially)

    try
    {
        manager.create( null, JACK_ID_OID, JACK_DTO );
        fail( "Shouldn't get here because account already exists!" );
    }
    catch( AppException e )
    {
        log.info( "Test is successful if you get here." );
        assertTrue( e.getHttpStatus() == Status.CONFLICT );
    }
}

A newer way: given( ... )

The new way began in Mockito, 1.9.5.rc1.

@Test
public void testCreate_newway() throws AppException
{
    given( dao.create( ( Account ) anyObject() ) ).will( returnsFirstArg() );
    when( partnerDao.readByOid( ACME_OID ) ).thenReturn( ACME );
    when( identityDao.readByOid( JACK_ID_OID ) ).thenReturn( JACK_ID );
    when( dao.readByIdentityAndPartneroids( any( ObjectId.class ), any( ObjectId.class ) ) ).thenReturn( null );

    AccountDto JACK_DTO = JACK.dto();
    JACK_DTO.setPartneroid( ACME_OID );
    JACK_DTO.setPassword( JACK_PASS );      // (have to inject this artificially)

    Account result = manager.create( null, JACK_ID_OID, JACK_DTO );

    verify( dao ).create( result );
    assertNotNull( result );
    assertTrue( EntityTestSupport.verifyPasswordHandled( result, JACK_PASS ) );
    assertTrue( EntityTestSupport.verifyAccountResult( JACK, result ) );
}

anyObject() and matchers

Sometimes Mockito is grumpy when you use anyObject() in an argument list with raw types (string literals and the like—see "eat this" below). The error displayed will tell you, but you need to bracket those with eq():

import static org.mockito.Matchers.anyObject;
...
import static org.mockito.Matchers.eq;
@Test
public void testCreate_newway() throws AppException
{
    ...
    when( mocked.method( eq( "eat this" ), ( SomeClass ) anyObject() ) ).thenReturn( something );
    ...
}

CALLS_REAL_METHODS

This is a way to instantiate an abstract class that you want to test. After doing this, it's as if SomeClass were not abstract.

    public class SomeClassTest
    {
        private SomeClass real;

        @Before
        public void setUp()
        {
            Mockito.mock( SomeClass.class, Mockito.CALLS_REAL_METHODS );
            real.setX( 9 );
            ...
        }

        @Test
        public void testSetX()
        {
            real.setX( 9 );
            assertEquals( 9, read.getX() );
        }
    }

    public abstract class SomeClass
    {
        private int x;
        ...
        public void setX( int x ) { this.x = x; }
        public int getX() { return this.x; }
        ...
    }

Supposedly mocked code is executed

This still picks on me from time to time. I'm debugging through some code expecting not to execute a method call because it's mocked, but it crashes down inside (or does the wrong thing down inside) and I ask myself why Mockito didn't mock the method.

The answer is that Mockito will not mock methods that are static or final. In order to do that, remove final, re-interface above the class or visit PowerMock's functionality.


Catch-exception example

Here is some code that demonstrates a more elegant way of catching and verifying exceptions (predicted and on-purpose) in test code. Here we're testing the address manager of some web application. It's thin, it's simple, but we're doing it anyway to show this example. Code that implements validation of the address, complex, going over the wire to a third-party service, is what we're mocking. The AddressValidator chooses which of several possible validations to have the underlying Validator perform.

Spanning so much depth might not be the right way to do this, but I'm exploring it here also to hint at an underlying BaseValidator handling some dependency injection to prime the mocking pump. (Yes, this is essentially a note to myself and not a point I'm trying to make to anyone else.)

To accomplish this, we're mixing some Mockito and catch-exception, a library (free) from Google code.

The first, principal method, the one illustrating success, is pure Mockito. It's the second one, a mixture, that illustrates catch-exception since failure throws an AppException.

package com.acme;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.when;
import static org.mockito.Matchers.anyObject;
import static com.googlecode.catchexception.CatchException.caughtException;
import static com.googlecode.catchexception.CatchException.verifyException;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import com.acme.pojo.Address
import com.acme.exception.AppException;
import com.acme.validator.Validator;
import com.acme.validator.AddressValidator;

public class AddressManagerTest
{
    private final static String STREET  = "21 Jump Street";
    private final static String CITY    = "Beverley Hills";
    private final static String STATE   = "CA";
    private final static String COUNTRY = "US";
    private final static String ZIP     = "12345";

    private AddressManager  manager;   // class under test
    private Address         proposed;  // address POJO, as if from service layer...

    @Mock private Validator validator; // mocked; what the address validator calls

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

        // make sure the mocked object gets injected into the object under test...
        manager = new AddressManager( validator );

        proposed = new Address();
        proposed.setStreet1( STREET );
        proposed.setCity( CITY );
        proposed.setState( STATE );
        proposed.setCountry( COUNTRY );
        proposed.setPostalcode( ZIP );
    }

    @Test
    public void testVerifyAddress_success() throws AppException
    {
        SetupThreadContext.erectCaller();

        when( validator.validateAddress( ( Address ) anyObject() ) ).thenReturn( true );

        // if successful, this just returns proposed...
        Address result = manager.verifyAddress( proposed );

        assertTrue( result == proposed );
    }

    @Test
    public void testVerifyAddress_failure() throws AppException
    {
        SetupThreadContext.erectCaller();

        // failing case throws an AppException with a specific message we can test for
        when( validator.validateAddress( ( Address ) anyObject() ) ).thenReturn( false );
        verifyException( manager, AppException.class ).verifyAddress( proposed );

        assertEquals( caughtException().getMessage(), AddressValidator.ADDRESS_FAILURE );
    }
}

Here's some background illustration (again, for me, not really for anyone else).

AddressValidator.java:
public class AddressValidator extends BaseValidator
{
    public static final String ADDRESS_FAILURE = "service disapproves address";

    public AddressValidator( Validator validator )
    {
        super( validator );
    }

    public AppException validate( Address address, Logger log ) throws AppException
    {
        boolean okay;

        try
        {
            okay = getValidator().validateAddress( address );

            if( !okay )
                return new AppException( ADDRESS_FAILURE );
        }
        .
        .
        .
BaseValidator.java:
package com.hp.web.validator;

public abstract class BaseValidator
{
    private Validator validator;

    public BaseValidator( Validator validator ) { this.validator = validator; }
    public Validator getValidator() { return validator; }
}

"Cannot resolve method 'thenReturn()'"

For this code, ...

    when( mockedObject.stubbedMethod() ).thenReturn( X );

...the compiler give you this error:

    Cannot resolve method 'thenReturn( X )'

This only means that X doesn't match what stubbedMethod() should return.

Concrete example: I have mocked AmazonSqsClient and want to specify how method GetQueueAttributes() should pretend to behave. I get:

Cannot resolve method 'thenReturn(resultMap)'

...in this code:

public class HaveFunWithSqs
{
  private SqsOperations         sqsOperations;
  @Mock private AmazonSqsClient awsClient;

  @BeforeMethod
  public void setup()
  {
    MockitoAnnotations.initMocks( this );
    sqsOperations = new SqsOperations( /* stuff about queue */ );
  }

  @Test
  public void test()
  {
    List< String > attributeNames = new ArrayList<>( 1 );
    attributeNames.add( "ApproximateNumberOfMessages" );
    Map< String, String > resultMap = new HashMap<>( 1 );
    resultMap.put( "ApproximateNumberOfMessages", "27" );

    when( awsClient.getQueueAttributes( attributeNames ) ).thenReturn( resultMap );

    int result = sqsOperations.getMessageCount();

    assertEqual( result, 27 );
  }
}

What I forgot was that AmazonSqsClient.getQueueAttribtes() returns the intermediate object, GetQueueAttributesResult; the resulting map I'm after is inside that:

@Test
public void test()
{
    List< String > attributeNames = new ArrayList<>( 1 );
    attributeNames.add( "ApproximateNumberOfMessages" );
    Map< String, String > resultMap = new HashMap<>( 1 );
    resultMap.put( "ApproximateNumberOfMessages", "27" );
    GetQueueAttributesResult attributesResult = new GetQueueAttributesResult();
    attibutesResult.setAttributes( resultMap );

    when( awsClient.getQueueAttributes( attributeNames ) ).thenReturn( attributesResult );

    int result = sqsOperations.getMessageCount();

    assertEqual( result, 27 );
}

Faking, mocking and stubbing...

Martin Fowler:

Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production.

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.

Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

From xunitpattern:

Mock Object: that implements the same interface as an object on which the SUT depends. We can use a Mock Object as an observation point when we need to do Behavior Verification to avoid having an Untested Requirement (see Production Bugs on page X) caused by an inability to observe side-effects of invoking methods on the SUT.

Stub: This implementation is configured to respond to calls from the SUT with the values (or exceptions) that will exercise the Untested Code (see Production Bugs on page X) within the SUT. A key indication for using a Test Stub is having Untested Code caused by the inability to control the indirect inputs of the SUT

Fake: We acquire or build a very lightweight implementation of the same functionality as provided by a component that the SUT depends on and instruct the SUT to use it instead of the real.

Another look...

Fake: a class that implements an interface but contains fixed data and no logic. Simply returns "good" or "bad" data depending on the implementation.

Mock: a class that implements an interface and allows the ability to dynamically set the values to return/exceptions to throw from particular methods and provides the ability to check if particular methods have been called/not called.

Stub: Like a mock class, except that it doesn't provide the ability to verify that methods have been called/not called.

And...

Stub: an object that provides predefined answers to method calls.

Mock: an object on which you set expectations.

Fake: an object with limited capabilities (for the purposes of testing), e.g. a fake web service.


Links...