VitalyPolonetsky
1,345 views
28 slides
Aug 01, 2015
Slide 1 of 28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
About This Presentation
Presentation about Mockito mocking framework for Java
Size: 348.56 KB
Language: en
Added: Aug 01, 2015
Slides: 28 pages
Slide Content
Mock your way with Mockito Are you mocking me ? by Vitaly Polonetsky June 2012
Mockito Mocking framework that tastes really good http://code.google.com/p/mockito/
Agenda Basics Main features Integration Demo Additional features
Basics Stubbing Verifing
How do you drink it ? import static org.mockito.Mockito .*; Stub method calls Prepare test cases Can replace DBUnit (integration tests) for unit tests Verify interactions Verify method invocations
How do you drink it ? (cont.) Let’s write a class with some logic: public class ComplexStrategy { public int compute1(Items list) { return list.get (0) + list.get (1); } public int compute2(Items list) { return 2 * list.get (0); } }
Stub method calls // Mock interfaces or concrete classes Items list = mock( Items.class ); // Stubbing when( list.get (0)). thenReturn (5); when( list.get (1)). thenReturn (7); // Calling method that causes interaction with the mock int result = complexStrategy.compute1(list); // Test assertions Assert.assertEquals (5 + 7, result); By default, for all methods that return value, mock returns null, an empty collection or appropriate primitive/primitive wrapper value ( e.g : 0, false, ... for int /Integer, boolean /Boolean, ...).
Verify interactions // Mock interfaces or concrete classes Items list = mock( Items.class ); // Stubbing when( list.get (0)). thenReturn (1); // Calling method that causes interaction with the mock int result = complexStrategy.compute1(list); // Test interactions verify(list).get(0); Once created, mock will remember all interactions. Then you can selectively verify whatever interaction you are interested in.
Difference in stubbing and verifying method arguments Stubbing: Method call inside when() call when ( mock . method ( args ) ) .then… Verifying: Method call outside of verify() call verify ( mock ) . method ( args )
Main features Argument matchers Number of interactions and invocations Annotations Methods returning void
Argument matchers when( svc.get (" someId ")).then … The default matching of the passed argument “ someId ” is using the equals() method To introduce smart matcher, you can use the org.hamcrest.Matcher interface and the classes that implement it: when( svc.get (any()).then… when( svc.get ( argThat (matcher))).then… At the same stub setup, you should either declare all arguments as plain objects, or all of them using matchers If you need to combine, you can use the eq () matcher
Argument matchers (cont.) Mockito class provides many built-in matchers, some of them: eq () , any(), isA (), isNull (), notNull () anyInt (), anyBoolean (), anyFloat () anyString (), contains(), startsWith (), endsWith (), matches() anyCollection (), anyList (), anyMap (), anySet () refEq () And type-safe matcher wrappers: argThat () intThat (), booleanThat (), floatThat () Other matchers in AdditionalMatchers class: and(), or(), not(), gt (), lt (), geq (), leq () aryEq (), cmpEq ()
Verify number of invocations Invoked once: verify( mockedList ).add("once"); verify( mockedList , times(1)).add("once"); Invoked exactly x times: verify( mockedList , times(2)).add("twice"); verify( mockedList , times(3)).add("three times"); Never: verify( mockedList , never()).add("never happened"); verify( mockedList , times(0)).add("never happened"); At least / at most: verify( mockedList , atLeastOnce ()).add("three times"); verify( mockedList , atLeast (2)).add("five times"); verify( mockedList , atMost (5)).add("three times");
Check no interactions with mock No interactions at all: verifyZeroInteractions ( someMock ); No redundant invocations: verify( mockedList ).add("one"); verifyNoMoreInteractions ( mockedList ); Use of verify(mock, never()) is preferred, no interactions with mock should be checked rarely
@Mock annotation Minimizes repetitive mock creation code Makes the test class more readable Makes the verification error easier to read (field name is shown) public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider ; private ArticleManager manager; … } MockitoAnnotations.initMocks ( articleManagerTestObj );
Stubbing void methods when( svc.noReturn ()).then … Oops, you can’t use the response from noReturn () Use this instead: doThrow (new RuntimeException ()) .when(svc) . noReturn (); Other methods: doReturn (Object) doThrow ( Throwable ) doThrow (Class) doAnswer (Answer) doNothing () doCallRealMethod ()
Spying Unfortunately some classes are loosely coupled with no interface, in this case we can spy on real objects: List list = new LinkedList (); List spy = spy(list); //optionally, you can stub out some methods: when( spy.size ()). thenReturn (100); //using the spy calls *real* methods spy.add ("one"); spy.add ("two"); //prints "one" - the first element of a list System.out.println ( spy.get (0)); //size() method was stubbed - 100 is printed System.out.println ( spy.size ()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two");
Spying (cont.) Sometimes when(Object) can’t be used to stub spies. In these cases doReturn () / doAnswer () / doThrow () family of methods should be used. List list = new LinkedList (); List spy = spy(list); //real method is called, throws IndexOutOfBoundsException when( spy.get (0)). thenReturn (" foo "); Passed real instance is not used, a copy of it is created. Therefore you should not interact with the real instance. Final methods can’t be mocked and/or verified. DUH!!!
@Spy and @ InjectMocks annotations @Spy – instead of spy(Object) @ InjectMocks – injects mock or spy fields into tested object automatically Initialization using: MockitoAnnotations.initMocks (Object) Automatic instantiation of @Spy and @ InjectMocks : //instead: @Spy BeerDrinker drinker = new BeerDrinker (); //you can write: @Spy BeerDrinker drinker; //same applies to @ InjectMocks annotation: @ InjectMocks LocalPub pub;
Integration Straight forward using Spring JUnit runner
Integration using Spring Simple XML initialization: <bean id=" dao " class=" org.mockito.Mockito " factory-method="mock"> <constructor- arg value=" com.package.Dao " /> </bean> Spring XML initialization with autowiring support: <bean id=" dao " class=" org.springframework.aop.framework.ProxyFactoryBean "> <property name="target"> <bean class=" org.mockito.Mockito " factory-method="mock"> <constructor- arg value=" com.package.Dao " /> </bean> </property> <property name=" proxyInterfaces "> <value> com.package.Dao </value> </property> </bean> Springockito : < mockito:mock id=" dao " class=" com.package.Dao " />
JUnit Runner Mocks are the base of unit tests, so Mockito provides JUnit runner out of the box: @ RunWith ( MockitoJUnitRunner.class ) public class MyTest { … } Initializes annotations in the test class Bake the mock differently for each test
Additional features Verifying order of invocations InOrder inOrder = inOrder (mock); inOrder.verify (… inOrder.verify (… Stubbing consecutive calls when( mock.someMethod ()) . thenThrow (new RuntimeException ()) . thenReturn (" foo "); Stubbing with callbacks add implementation to mock method
Additional features (cont.) Capturing arguments and @Captor Real partial mocks: Spy is one kind of partial mock Another option is to use: when(mock…). thenCallRealMethod (); Resetting mocks – make mock forget about interactions & stubbing (poorly written test): reset(mock); Verification with timeout