Mockito is one of the most popular mocking framework for java. For me, it is frequently used in daily unit test . I would like to note down some basic usages.
Unit Test and Mocking
We do need the unit test to test our method, our interface, our class, to see whether it performs correctly, especially for methods with complicated business logic. When testing an object which has dependencies on other complex objects, you do not want to create real objects for the unit test. Here comes the mocking that mimics the behavior of real objects.
Basic Mockito
Mockito three phrases:
Mock away external dependencies and insert the mocks into the code under test
Execute the code under test
Validate that the code executed correctly
Here is an example I would like to use. Suppose I have a StockService.
Use @Mock to create mock objects. Add MockitoAnnotations.initMocks(this) to populate the annotated fields. Utilize when(...).thenReturn(...) or when(…).thenThrow(…) to imitate methods. Verify the results via verify() / assert() to check logic.
Spy & ArgumentCaptor
@Spy or spy() means you want to spying on the real objects which can be associated with “partial mocking” concept. Take real into consideration. There exists difference in using when(…).thenReturn(…) and doReturn(...).when(...)
1 2 3 4 5 6 7 8
List list = new LinkedList(); List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
At the same time, we can make use of ArgumentCaptor to verifies argument values. It is recommended to use ArgumentCaptor with verification but not with stubbing. In some situations though, it is helpful to assert on certain arguments after the actual verification. Suppose that we want to test whether the stock is added to stockList via addStockToPortfolio() , argumentCaptor could be a way to captor and test.
Besides to setter to access to private field and mock its method, we can use Guava’ s @VisibleForTesting to help us. Here is one example. Suppose I remove autocomplete and quote services from constructor.
public StockService() {
portfolio = new ArrayList<>();
autoComplete = ..;
quotes = ..;
}
@VisibleForTesting
public StockService(AutoComplete autoComplete, Quotes quotes) {
portfolio = new ArrayList<>();
this.autoComplete = autoComplete;
this.quotes = quotes;
}