Mockito Practice

Common
1
2
3
//Let's import Mockito statically so that the code looks clearer
import static org.mockito.Mockito.*;
import static org.mockito.BDDMockito.*;

Stub 類

  • [2] How about some stubbing?
  • [5] Stubbing void methods with exceptionss
  • [10] Stubbing consecutive calls (iterator-style stubbing)
  • [11] Stubbing with callbacks
  • [12] doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() family of methods
  • [16] Real partial mocks (Since 1.8.0)
  • [17] Changing default return values of unstubbed invocations (Since 1.7)
  • [18] Resetting mocks (Since 1.8.0)
  • [24] One-liner stubs (Since 1.9.0)

Stub 類說明

  • [2] How about some stubbing?
How about some stubbing?
1
2
3
4
5
6
7
8
9
10
11
12
//stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());

//following prints "first"
System.out.println(mockedList.get(0));

//following throws runtime exception
System.out.println(mockedList.get(1));

//following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
  • [5] Stubbing void methods with exceptionss
Stubbing void methods with exceptions
1
2
3
4
doThrow(new RuntimeException()).when(mockedList).clear();

//following throws RuntimeException:
mockedList.clear();
  • [10] Stubbing consecutive calls (iterator-style stubbing)
Stubbing consecutive calls (iterator-style stubbing)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

//Any consecutive call: prints "foo" as well (last stubbing wins).
System.out.println(mock.someMethod("some arg"));

when(mock.someMethod()).thenReturn("one", "two", "three");
assertEquals("one",mock.someMethod());
assertEquals("two",mock.someMethod());
assertEquals("three",mock.someMethod());
assertEquals("three",mock.someMethod());
assertEquals("three",mock.someMethod());
  • [11] Stubbing with callbacks
Stubbing with callbacks
1
2
3
4
5
6
7
8
9
10
when(mock.someMethod(anyString())).thenAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Object mock = invocation.getMock();
return "called with arguments: " + args;
}
});

//Following prints "called with arguments: foo"
System.out.println(mock.someMethod("foo"));
  • [12] doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() family of methods
doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() family of methods
1
2
3
4
doThrow(new RuntimeException()).when(mockedList).clear();

//following throws RuntimeException:
mockedList.clear();
  • [16] Real partial mocks (Since 1.8.0)
Real partial mocks (Since 1.8.0)
1
2
3
4
5
6
7
8
//you can create partial mock with spy() method:
List list = spy(new LinkedList());

//you can enable partial mock capabilities selectively on mocks:
Foo mock = mock(Foo.class);
//Be sure the real implementation is 'safe'.
//If real implementation throws exceptions or depends on specific state of the object then you're in trouble.
when(mock.someMethod()).thenCallRealMethod();
  • [17] Changing default return values of unstubbed invocations (Since 1.7)
Changing default return values of unstubbed invocations (Since 1.7)
1
2
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
  • [18] Resetting mocks (Since 1.8.0)
Resetting mocks (Since 1.8.0)
1
2
3
4
5
6
List mock = mock(List.class);
when(mock.size()).thenReturn(10);
mock.add(1);

reset(mock);
//at this point the mock forgot any interactions & stubbing
  • [24] One-liner stubs (Since 1.9.0)
One-liner stubs (Since 1.9.0)
1
2
3
4
5
public class CarTest {
Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();

@Test public void should... {}
}

Matchers 類

  • [3] Argument matchers
Argument matchers
1
2
3
4
5
6
7
8
9
10
11
//stubbing using built-in anyInt() argument matcher
when(mockedList.get(anyInt())).thenReturn("element");

//stubbing using hamcrest (let's say isValid() returns your own hamcrest matcher):
when(mockedList.contains(argThat(isValid()))).thenReturn("element");

//following prints "element"
System.out.println(mockedList.get(999));

//you can also verify using an argument matcher
verify(mockedList).get(anyInt());
如果使用 matcher 的話,每一個都必須用 matcher
1
2
3
4
5
verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
//above is correct - eq() is also an argument matcher

verify(mock).someMethod(anyInt(), anyString(), "third argument");
//above is incorrect - exception will be thrown because third argument is given without an argument matcher.

Verify 類

  • [1] Let’s verify some behaviour!
  • [4] Verifying exact number of invocations / at least x / never
  • [6] Verification in order(驗證操作順序)
  • [7] Making sure interaction(s) never happened on mock(驗證無任何互動)
  • [8] Finding redundant invocations(驗證所有互動是否皆驗證到)
  • [15] Capturing arguments for further assertions (Since 1.8.0)
  • [22] Verification with timeout (Since 1.8.5)
  • [25] Verification ignoring stubs (Since 1.9.0)

Verify 類說明

  • [1] Let’s verify some behaviour!
Let's verify some behaviour!
1
2
3
4
5
6
7
8
9
10
//mock creation
List mockedList = mock(List.class);

//using mock object
mockedList.add("one");
mockedList.clear();

//verification
verify(mockedList).add("one");
verify(mockedList).clear();
  • [4] Verifying exact number of invocations / at least x / never
Verifying exact number of invocations / at least x / never
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
//using mock
mockedList.add("once");

mockedList.add("twice");
mockedList.add("twice");

mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");

//following two verifications work exactly the same - times(1) is used by default
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once");

//exact number of invocations verification
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");

//verification using never(). never() is an alias to times(0)
verify(mockedList, never()).add("never happened");

//verification using atLeast()/atMost()
verify(mockedList, atLeastOnce()).add("once");
verify(mockedList, atLeast(2)).add("twice");
verify(mockedList, atMost(5)).add("three times");
  • [6] Verification in order(驗證操作順序)
Verification in order
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
29
30
// A. Single mock whose methods must be invoked in a particular order
List singleMock = mock(List.class);

//using a single mock
singleMock.add("was added first");
singleMock.add("was added second");

//create an inOrder verifier for a single mock
InOrder inOrder = inOrder(singleMock);

//following will make sure that add is first called with "was added first, then with "was added second"
inOrder.verify(singleMock).add("was added first");
inOrder.verify(singleMock).add("was added second");

// B. Multiple mocks that must be used in a particular order
List firstMock = mock(List.class);
List secondMock = mock(List.class);

//using mocks
firstMock.add("was called first");
secondMock.add("was called second");

//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);

//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");

// Oh, and A + B can be mixed together at will
  • [7] Making sure interaction(s) never happened on mock(驗證無任何互動)
Making sure interaction(s) never happened on mock
1
2
3
4
5
6
7
8
9
10
11
//using mocks - only mockOne is interacted
mockOne.add("one");

//ordinary verification
verify(mockOne).add("one");

//verify that method was never called on a mock
verify(mockOne, never()).add("two");

//verify that other mocks were not interacted
verifyZeroInteractions(mockTwo, mockThree);
  • [8] Finding redundant invocations(驗證所有互動是否皆驗證到)
Finding redundant invocations
1
2
3
4
5
6
7
8
//using mocks
mockedList.add("one");
mockedList.add("two");

verify(mockedList).add("one");

//following verification will fail
verifyNoMoreInteractions(mockedList);
  • [15] Capturing arguments for further assertions (Since 1.8.0)
Capturing arguments for further assertions (Since 1.8.0)
1
2
3
4
5
6
7
8
9
10
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
mock.doSomething(mock);
verify(mock).doSomething(argument.capture());
assertEquals(mock, argument.getValue());

class Person{
Person doSomething(Person abc){
return abc;
}
}
  • [22] Verification with timeout (Since 1.8.5)
Verification with timeout (Since 1.8.5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//passes when someMethod() is called within given time span
verify(mock, timeout(100)).someMethod();
//above is an alias to:
verify(mock, timeout(100).times(1)).someMethod();

//passes when someMethod() is called *exactly* 2 times within given time span
verify(mock, timeout(100).times(2)).someMethod();

//passes when someMethod() is called *at least* 2 times within given time span
verify(mock, timeout(100).atLeast(2)).someMethod();

//verifies someMethod() within given time span using given verification mode
//useful only if you have your own custom verification modes.
verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
  • [25] Verification ignoring stubs (Since 1.9.0)
Verification ignoring stubs (Since 1.9.0)
1
2
3
4
5
6
7
8
9
10
11
verify(mock).foo();
verify(mockTwo).bar();

//ignores all stubbed methods:
verifyNoMoreInvocations(ignoreStubs(mock, mockTwo));

//creates InOrder that will ignore stubbed
InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo));
inOrder.verify(mock).foo();
inOrder.verify(mockTwo).bar();
inOrder.verifyNoMoreInteractions();

BDD

  • [19] Aliases for behavior driven development (Since 1.8.0)
  • [29] (new) BDD style verification (Since 1.10.0)
Aliases for behavior driven development (Since 1.8.0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import static org.mockito.BDDMockito.*;

Seller seller = mock(Seller.class);
Shop shop = new Shop(seller);

public void shouldBuyBread() throws Exception {
//given
given(seller.askForBread()).willReturn(new Bread());

//when
Goods goods = shop.buyBread();

//then
assertThat(goods, containBread());
}
(new) BDD style verification (Since 1.10.0)
1
then(person).should(times(2)).ride(bike);

Mockito

  • [9] Shorthand for mocks creation - @Mock annotation
  • [13] Spying on real objects
  • [21] New annotations: @Captor, @Spy, @InjectMocks (Since 1.8.3)
  • [23] Automatic instantiation of @Spies, @InjectMocks and constructor injection goodness (Since 1.9.0)
  • [26] Mocking details (Since 1.9.5) (辨別物件是 mock or spy)
  • [30] (new) Spying or mocking abstract classes (Since 1.10.12)

Mockito 說明

  • [9] Shorthand for mocks creation - @Mock annotation

自動生成Mock類
在需要Mock的屬性上標記@Mock注解
然後@RunWith(MockitoJUnitRunner.class)
或者在setUp()方法中顯示調用MockitoAnnotations.initMocks(this);生成Mock類即可。

Important! This needs to be somewhere in the base class or a test runner:

Shorthand for mocks creation - @Mock annotation
1
2
3
4
5
6
7
8
9
public class ArticleManagerTest {

@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;

private ArticleManager manager;
//...
}

  • [13] Spying on real objects
Spying on real objects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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");
Let
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);
  • [21] New annotations: @Captor, @Spy, @InjectMocks (Since 1.8.3)

    • @Captor simplifies creation of ArgumentCaptor - useful when the argument to capture is a nasty generic class and you want to avoid compiler warnings
    • @Spy - you can use it instead spy(Object).
    • @InjectMocks - injects mock or spy fields into tested object automatically.
  • [23] Automatic instantiation of @Spies, @InjectMocks and constructor injection goodness (Since 1.9.0)

Automatic instantiation of @Spies, @InjectMocks and constructor injection goodness (Since 1.9.0)
1
2
3
4
5
6
7
//instead:
@Spy BeerDrinker drinker = new BeerDrinker();
//you can write:
@Spy BeerDrinker drinker;

//same applies to @InjectMocks annotation:
@InjectMocks LocalPub;
  • [26] Mocking details (Since 1.9.5) (辨別物件是 mock or spy)
Mocking details (Since 1.9.5) (辨別物件是 mock or spy)
1
2
Mockito.mockingDetails(someObject).isMock();
Mockito.mockingDetails(someObject).isSpy();
  • [30] (new) Spying or mocking abstract classes (Since 1.10.12)
(new) Spying or mocking abstract classes (Since 1.10.12)
1
2
3
4
5
6
7
8
9
10
//convenience API, new overloaded spy() method:
SomeAbstract spy = spy(SomeAbstract.class);

//Robust API, via settings builder:
OtherAbstract spy = mock(OtherAbstract.class, withSettings()
.useConstructor().defaultAnswer(CALLS_REAL_METHODS));

//Mocking a non-static inner abstract class:
InnerAbstract spy = mock(InnerAbstract.class, withSettings()
.useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));

Others

  • [18] Troubleshooting & validating framework usage (Since 1.8.0)
  • [20] Serializable mocks (Since 1.8.1)
  • [27] Delegate calls to real instance (Since 1.9.5)
  • [28] MockMaker API (Since 1.9.5)

Practice

mock reset practice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List mock = mock(List.class);
mock.add(100);
verify(mock).add(100);
assertEquals(0,mock.size());

when(mock.size()).thenReturn(10);

mock.add(101);
verify(mock).add(101);
verify(mock).add(101);
reset(mock);
//verify(mock).add(101);
assertEquals(0,mock.size());
assertNull(mock.get(0));
assertNull(mock.get(1));
spy reset practice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List spy = spy(new LinkedList());

spy.add(100);
verify(spy).add(100);
assertEquals(1,spy.size());

when(spy.size()).thenReturn(10);

spy.add(101);
verify(spy).add(101);
verify(spy).add(101);
assertEquals(10,spy.size());
reset(spy);
//verify(spy).add(101);
assertEquals(2, spy.size());
assertEquals(100, spy.get(0));
assertEquals(101, spy.get(1));
isMock isSpy doCallRealMethod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Person mock = mock(Person.class);
Person spy = spy(new Person());

assertTrue(Mockito.mockingDetails(mock).isMock());
assertTrue(Mockito.mockingDetails(spy).isSpy());

assertNull(mock.someMethod());
doCallRealMethod().when(mock).someMethod();
assertEquals("Yume",mock.someMethod());

class Person{
String someMethod(){
return "Yume";
}
void foo(){}
void bar(){}
}
@InjectMocks @Spy @Mock
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
@InjectMocks Person person = new Person();
@InjectMocks Person person1 = mock(Person.class);
@InjectMocks Person person2 = spy(new Person());
//@InjectMocks @Spy Person person3;
@Spy Person person4;
@Mock Person person5;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}

assertEquals("Yume", person.someMethod());
assertNull(person1.someMethod());
assertEquals("Yume", person2.someMethod());

assertEquals("Yume", person4.someMethod());
assertNull(person5.someMethod());

class Person{
String someMethod(){
return "Yume";
}
void foo(){}
void bar(){}
}
BDD
1
2
3
given(mock.someMethod()).willReturn("Dream");
assertEquals("Dream", mock.someMethod());
then(mock).should(times(1)).someMethod();