Mockito
See also
Read the guide to testing in IBEX before reading this guide.
For more detailed information on Mockito, see the Mockito homepage and the Mockito documentation.
Test Doubles
Test doubles are objects that stand in for a real object, for the purposes of unit testing. Terminology varies but there are four usual types that are described:
Dummy - an object that is passed around but not directly used by the method under test
Fake - a working implementation of a class with a simplified internal implementation, for example an in memory database where the production implementation uses a persistent database
Stub - an object that provides a canned answer to a method call
Mock - fake objects which know about which method calls they receive
See this article for more information. Mockito mostly helps with Stub and Mock doubles.
Verifying Interactions
To create a mock object using Mockito, in a way which is type-safe and works with generics, use the @Mock
annotation:
import org.mockito.Mock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;
import java.util.List;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class SomeTest {
@Mock private List<String> mockedList;
@Test
public void myUnitTest() {
// 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();
}
}
Important
The test class must be annotated with @RunWith(MockitoJUnitRunner.StrictStubs.class)
- otherwise the @Mock
annotation will not be processed, and the mock object will be null
during the test.
In the above example, the generic List<String>
interface is mocked, and has some method calls made on it.
The verify calls replace the usual assert calls in this unit test, and check the method calls were made.
For non-generic classes, it is possible to use an older syntax to create the mock inline:
SomeClass mockedList = mock(SomeClass.class);
See also
The Mockito Mock documentation contains further details about how to construct mocks for more advanced use-cases.
Stubbing Method Calls
@Mock private LinkedList<String> mockedList;
@Test
public void myUnitTest() {
// 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));
}
This time the concrete class LinkedList
is mocked instead of an interface.
The mocked object returns what is asked of it when the method call is made with identical arguments.
See also
The Mockito documentation contains detailed documentation about how Mockito can be used to mock method calls for various cases.
Times Method is Called
Mockito has several options for checking how many times a particular method is called:
atLeast(int minNumber)
at least this many timesatLeastOnce()
at least onceatMost(int maxNumber)
at most this many timesnever()
same astimes(0)
times(int number)
exactly this number of times
The default is times(1)
.
Any Methods
When verifying method calls, if the value of an argument is not important, Mockito allows you to check that any object of a specific type was used as an argument instead.
// The initialisable observer has its update method called once
verify(mockObserver, times(1)).update(value, any(Exception.class), anyBoolean());
For common types methods such as anyString()
are available, otherwise any(Object.class)
can be used. A null
object will also be matched by using any.
See the Mockito ArgumentMatchers
documentation for more details.
Capturing Values on Method Calls
If you want to capture the object called in a method, perhaps to check some value, then a captor can be used. See the code below for an example of how to do this.
@Captor private ArgumentCaptor<Exception> exceptionCaptor;
@Mock private InitialisableObserver<String> mockObserver;
@Mock private Converter<Integer, String> mockConverter;
@Test
public void test_ConvertingObservable_with_conversion_exception() throws ConversionException {
//Arrange
// initObservable is what our ConvertingObservable looks at, and testObservable we can call set methods on
TestableObservable<Integer> testObservable = new TestableObservable<>();
InitialiseOnSubscribeObservable<Integer> initObservable = new InitialiseOnSubscribeObservable<Integer>(testObservable);
// converter with a stub conversion method
when(mockConverter.convert(123)).thenThrow(new ConversionException("conversion exception!"));
// Object we are really testing
ConvertingObservable<Integer, String> convertObservable = new ConvertingObservable<>(initObservable, mockConverter);
//Act
convertObservable.addObserver(mockObserver);
convertObservable.setSource(initObservable);
testObservable.setValue(123);
//Assert
// The initialisable observer has its onError message called once, for the ConversionException
verify(mockObserver, times(0)).onValue(anyString());
verify(mockObserver, times(1)).onError(exceptionCaptor.capture());
assertEquals("conversion exception!", exceptionCaptor.getValue().getMessage());
}
Important
As with the @Mock
annotation, the @Captor
annotation will only be processed if the test class is annotated with
@RunWith(MockitoJUnitRunner.StrictStubs.class)
.
Checking Order of Method Calls
Mockito can be used to check the order methods were called in.
InOrder inOrder = inOrder(firstMock, secondMock);
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
Spies
Spies can be used to stub a method or verify calls on a real class. Needing to use a partial mock like this might be a symptom of problems with code though!
// These are equivalent, but the first is the preferred approach
@Spy Foo spyOnFoo = new Foo("argument");
Foo spyOnFoo = Mockito.spy(new Foo("argument"));
Examples
IBEX Observable
Below is a full example, showing how the verification and stubbing can be used to check behaviour of an observable.
In this example, InitialiseOnSubscribeObservable
takes another observable as its argument, gets the current value of
that observable, and listens for changes. Here we stub the class that InitialiseOnSubscribeObservable
is observing,
to simplify the test. The only method call we are testing is getValue()
.
The InitialisableObserver
is also mocked. As part of the test we want to check that it has its update()
method
called with a specific set of arguments. We use times(1)
to specify we want the method called exactly once.
@Mock private InitialisableObserver<String> mockObserver;
@Mock private CachingObservable<String> mockObservable;
@Test
public void test_InitialiseOnSubscribeObservable_subscription() {
//Arrange
String value = "value";
when(mockObservable.getValue()).thenReturn(value);
// Object we are really testing
InitialiseOnSubscribeObservable<String> initObservable =
new InitialiseOnSubscribeObservable<>(mockObservable);
//Act
Object returned = initObservable.addObserver(mockObserver);
//Assert: The initialisable observer has its update method called once
verify(mockObserver, times(1)).update(value, null, false);
// The InitialiseOnSubscribeObservable has the value returned from the mock observable
assertEquals(value, initObservable.getValue());
// A Unsubscriber is returned
assertEquals(Unsubscriber.class, returned.getClass());
}
DB Tests using Answer
In RdbWritterTests
,
there is an example of using an answer to perform a more complicated return. The answer works like this:
when(mockPreparedStatement.executeQuery()).thenAnswer(resultAndStatement.new ResultsSetAnswer());
In this case the answer class is implemented as an inner class of another class, but this is not necessary. The answer looks like:
public class ResultsSetAnswer implements Answer<ResultSet> {
@Override
public ResultSet answer(InvocationOnMock invocation) throws Throwable {
openedResultsSet++;
return resultSet;
}
}
In the above example, the Answer
is used to keep track of the number of times a result set was opened; this Answer
implementation makes that information available in its parent class.
Tips and Advice
Use mocks to test interactions between a class and a particular interface
Use mocks to avoid unit tests touching complex or buggy dependencies
Do not mock type you don’t own? Perhaps…
Do not mock simple classes or value objects - may as well use the real thing
Do not mock everything!