Mock的好處是什麼?app
// 模擬LinkedList 的一個對象 LinkedList mockedList = mock(LinkedList.class); // 此時調用get方法,會返回null,由於尚未對方法調用的返回值作模擬 System.out.println(mockedList.get(0));
// 模擬獲取第一個元素時,返回字符串first。 給特定的方法調用返回固定值在官方說法中稱爲stub。 when(mockedList.get(0)).thenReturn("first"); // 此時打印輸出first System.out.println(mockedList.get(0));
// 模擬獲取第二個元素時,拋出RuntimeException when(mockedList.get(1)).thenThrow(new RuntimeException()); // 此時將會拋出RuntimeException System.out.println(mockedList.get(1)); 若是一個函數沒有返回值類型,那麼可使用此方法模擬異常拋出 doThrow(new RuntimeException("clear exception")).when(mockedList).clear(); mockedList.clear();
// anyInt()匹配任何int參數,這意味着參數爲任意值,其返回值均是element when(mockedList.get(anyInt())).thenReturn("element"); // 此時打印是element System.out.println(mockedList.get(999));
// 調用add一次 mockedList.add("once"); // 下面兩個寫法驗證效果同樣,均驗證add方法是否被調用了一次 verify(mockedList).add("once"); verify(mockedList, times(1)).add("once");
// mock creation List mockedList = mock(List.class); // using mock object mockedList.add("one"); mockedList.clear(); //verification verify(mockedList).add("one"); verify(mockedList).clear();
//You can mock concrete classes, not just interfaces LinkedList mockedList = mock(LinkedList.class); //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)); verify(mockedList).get(0);
//stubbing using built-in anyInt() argument matcher when(mockedList.get(anyInt())).thenReturn("element"); //stubbing using custom matcher (let's say isValid() returns your own matcher implementation): 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()); //argument matchers can also be written as Java 8 Lambdas verify(mockedList).add(someString -> someString.length() > 5);
//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("three times"); verify(mockedList, atLeast(2)).add("five times"); verify(mockedList, atMost(5)).add("three times");
doThrow(new RuntimeException()).when(mockedList).clear(); //following throws RuntimeException: mockedList.clear();
// 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
//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);
public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; @Before public void before(){ MockitoAnnotations.initMocks(this); } }
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")); // 第n次(n> 2),依舊以最後返回最後一個配置
when(mock.someMethod(anyString())).thenAnswer(new Answer() { Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); Object mock = invocation.getMock(); return "called with arguments: " + args; } }); //the following prints "called with arguments: foo" System.out.println(mock.someMethod("foo"));
能夠經過doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() 來自定義函數操做。ide
暗中調用真實對象函數
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");
Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS); Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class); verify(mock).doSomething(argument.capture()); assertEquals("John", argument.getValue().getName());
//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();