轉載:https://blog.csdn.net/sdyy321/article/details/38757135/html
官網: http://mockito.orgjava
源碼分析:http://www.javashuo.com/article/p-cspppwgm-gn.htmlgit
屬性默認值:https://yanbin.blog/mockito-mocked-default-fields-method-returns/#more-8359github
API文檔:http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.htmlspring
項目源碼:https://github.com/mockito/mockito
使用案例:https://blog.csdn.net/Christopher36/article/details/81036683app
首先添加maven依賴maven
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency>
固然mockito須要junit配合使用ide
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
而後爲了使代碼更簡潔,最好在測試類中導入靜態資源源碼分析
import static org.mockito.Mockito.*; import static org.junit.Assert.*;
下面咱們開始使用mockito來作測試單元測試
package com.spring.sxf.mockito; import org.junit.Test; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.exceptions.verification.NoInteractionsWanted; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import static org.mockito.Mockito.*; import static org.junit.Assert.*; /** * @author <a href="mailto:shangxiaofei@meituan.com">尚曉飛</a> * @date 7:52 PM 2019/4/26 */ public class MockitoTest { //驗證要mock的對象,是否發生過某些行爲 @Test public void testArrayList() { //生成mock對象 ArrayList<String> mockList = mock(ArrayList.class); //使用mock的對象 mockList.add("SXF"); mockList.add("456"); //驗證行爲add("SXF"),add("123")是否發生過 verify(mockList).add("SXF"); verify(mockList).add("456"); } //模擬咱們所指望的結果 @Test public void testArrayList1() { //生成mock對象 ArrayList<String> mockList = mock(ArrayList.class); // when(mockList.size()).thenReturn(2); int size = mockList.size(); assertEquals(2, size); } //模擬咱們指望的結果 @Test(expected = NullPointerException.class) public void when_thenThrow() throws IOException { OutputStream outputStream = mock(OutputStream.class); OutputStreamWriter writer = new OutputStreamWriter(outputStream); //預設當流關閉時拋出異常 doThrow(new IOException()).when(outputStream).close(); outputStream.close(); } //參數匹配 @Test public void with_arguments() { Comparable comparable = mock(Comparable.class); //預設根據不一樣的參數返回不一樣的結果 when(comparable.compareTo("Test")).thenReturn(1); when(comparable.compareTo("Omg")).thenReturn(2); assertEquals(1, comparable.compareTo("Test")); assertEquals(2, comparable.compareTo("Omg")); //對於沒有預設的狀況會返回默認值 assertEquals(0, comparable.compareTo("Not stub")); } //除了匹配製定參數外,還能夠匹配本身想要的任意參數 @Test public void with_unspecified_arguments() { List list = mock(List.class); //匹配任意參數 when(list.get(anyInt())).thenReturn(1); when(list.contains(argThat(new IsValid()))).thenReturn(true); assertEquals(1, list.get(1)); assertEquals(1, list.get(999)); assertTrue(list.contains(1)); assertTrue(!list.contains(3)); } private class IsValid extends ArgumentMatcher<List> { @Override public boolean matches(Object o) { return (Integer) o == 1 || (Integer) o == 2; } } //須要注意的是若是你使用了參數匹配,那麼全部的參數都必須經過matchers來匹配 @Test public void all_arguments_provided_by_matchers() { Comparator comparator = mock(Comparator.class); comparator.compare("nihao", "hello"); //若是你使用了參數匹配,那麼全部的參數都必須經過matchers來匹配 verify(comparator).compare(anyString(), eq("hello")); //下面的爲無效的參數匹配使用 //verify(comparator).compare(anyString(),"hello"); } //驗證確切的調用次數 @Test public void verifying_number_of_invocations() { List list = mock(List.class); list.add(1); list.add(2); list.add(2); list.add(3); list.add(3); list.add(3); //驗證是否被調用一次,等效於下面的times(1) verify(list).add(1); verify(list, times(1)).add(1); //驗證是否被調用2次 verify(list, times(2)).add(2); //驗證是否被調用3次 verify(list, times(3)).add(3); //驗證是否從未被調用過 verify(list, never()).add(4); //驗證至少調用一次 verify(list, atLeastOnce()).add(1); //驗證至少調用2次 verify(list, atLeast(2)).add(2); //驗證至多調用3次 verify(list, atMost(3)).add(3); } //模擬方法體拋出異常 @Test(expected = RuntimeException.class) public void doThrow_when() { List list = mock(List.class); doThrow(new Exception()).when(list).add(1); list.add(1); } //驗證執行順序 @Test public void verification_in_order() { List list = mock(List.class); List list2 = mock(List.class); list.add(1); list2.add("hello"); list.add(2); list2.add("world"); //將須要排序的mock對象放入InOrder InOrder inOrder = inOrder(list, list2); //下面的代碼不能顛倒順序,驗證執行順序 inOrder.verify(list).add(1); inOrder.verify(list2).add("hello"); inOrder.verify(list).add(2); inOrder.verify(list2).add("world"); } //確保模擬對象上無互動發生 @Test public void verify_interaction(){ List list = mock(List.class); List list2 = mock(List.class); List list3 = mock(List.class); list.add(1); verify(list).add(1); verify(list,never()).add(2); //驗證零互動行爲 verifyZeroInteractions(list2,list3); } //找出冗餘的互動(即未被驗證到的) @Test(expected = NoInteractionsWanted.class) public void find_redundant_interaction(){ List list = mock(List.class); list.add(1); list.add(2); verify(list,times(2)).add(anyInt()); //檢查是否有未被驗證的互動行爲,由於add(1)和add(2)都會被上面的anyInt()驗證到,因此下面的代碼會經過 verifyNoMoreInteractions(list); List list2 = mock(List.class); list2.add(1); list2.add(2); verify(list2).add(1); //檢查是否有未被驗證的互動行爲,由於add(2)沒有被驗證,因此下面的代碼會失敗拋出異常 verifyNoMoreInteractions(list2); } //九、使用註解來快速模擬 //在上面的測試中咱們在每一個測試方法裏都mock了一個List對象,爲了不重複的mock,是測試類更具備可讀性,咱們可使用下面的註解方式來快速模擬對象: @Mock private List mockList; //構造方法 public MockitoTest(){ MockitoAnnotations.initMocks(this); } @Test public void shorthand(){ mockList.add(1); verify(mockList).add(1); } }
1、單元測試類
@Slf4j @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"}) public class RouteServiceTest { //要被mock的接口 @Mock private IChannelQueueCountService iChannelQueueCountService; //使用了要被mock對象的類,須要注入mock對象 @InjectMocks @Autowired private ChannelChooseService channelChooseService; //發起調用的接口 @Autowired private TRouteService.Iface tRouteService; //mock對象注入 @Before public void setUp() { MockitoAnnotations.initMocks(this); } @Test public void test01() throws TException { when(iChannelQueueCountService.getChannelQueueCounts(anyList(), anyLong(), anyBoolean())).thenAnswer(new Answer<Map<Integer, Integer>>() { @Override public Map<Integer, Integer> answer(InvocationOnMock invocation) throws Throwable { HashMap<Integer, Integer> map = new HashMap<>(); Object[] args = invocation.getArguments(); List<Integer> ids = (List<Integer>) args[0]; for (Integer id : ids) { map.put(id, 1); } return map; } }); TChooseChannelReq tChooseChannelReq = new TChooseChannelReq(56789, 219, 999, 6000, "shangxiaofei", "6212260200052453285", TPPType.PRIVATE, 10, 34, 99999); TChooseChannelRes res = tRouteService.chooseChannel(tChooseChannelReq); System.out.println("接口調用返回:" + res.getLogicalChannelId()); } }