Mockito可以做哪些事情
1.驗證行爲
@Test
public void verify_behaviour() {
List mock = mock(List.class);
// 使用mock對象執行操作
mock.add(1);
mock.clear();
// 驗證操作是否執行
verify(mock).clear();
verify(mock).add(1);
}
注意:verify驗證操作是否執行,並不關心順序;但是如果需要順序上的驗證,那麼就需要每操作一步就驗證一步
2.模擬期望的結果
@Test
public void when_andReturn() {
Iterator mock = mock(Iterator.class);
//模擬期望的結果
when(mock.next()).thenReturn("first").thenReturn("2_n_time").thenReturn("haha");
//實際執行的結果
String actual = mock.next() + "\n" + mock.next() + "\n"+"haha";
//斷言
assertEquals("first\n2_n_time\nhaha", actual);
}
3.模擬方法體拋出異常
@Test(expected = RuntimeException.class)
public void exceptionTest(){
List mock = mock(List.class);
// 模擬拋出異常
doThrow(new RuntimeException()).when(mock).add(1);
mock.add(1);
}
4.使用註解快速模擬
@Mock
public Map mockMap;
@Before
public void setData(){
mockMap = new HashMap();
}
說明:使用Mock註解來創建對象,不過需要自己來new實現類;並且會有很多限制,使用時需要注意
5.參數匹配
@Test
public void argsMatch(){
Map map = mock(Map.class);
//模擬當 map put 時返回 1
when(map.put(anyString(),anyInt())).thenReturn(1);
map.put("2",2);
Integer rt= 1;
verify(map).put("2",2);
//斷言put 的返回值
assertEquals(rt, map.put("2",2));
}
說明:anyInt(),anyString() …可以匹配任意參數
6.期望異常
-
@Test(expected…)
@Test註解有一個可選的參數,”expected”允許你設置一個Throwable的子類。如果你想要驗證上面的canVote()方法拋出預期的異常,我們可以這樣寫:
@Test(expected = IllegalArgumentException.class ) public void canVote_throws_IllegalArgumentException_for_zero_age() { Student student = new Student(); student.canVote("0"); }
-
ExpectedException
如果要使用JUnit框架中的ExpectedException類,需要聲明ExpectedException異常
@Rule public ExpectedException thrown= ExpectedException.none();
然後你可以使用更加簡單的方式驗證預期的異常
@Test public void canVote_throws_IllegalArgumentException_for_zero_age() { Student student = new Student(); thrown.expect(IllegalArgumentException.class ); thrown.expectMessage("your exception msg"); student.canVote( 0 ); }
7.使用 PowerMock來 mock protected 和 private 方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(ComparativeActivityService.class)
@PowerMockIgnore("javax.management.*")
public class GrouponOrderServiceImplTest {
@Before
public void setUp() throws Exception {
//使用反射的方式 mock protected、 private 方法,但是一般情況下是不應該 mock 這些方法的
PowerMockito.doReturn(false).when(comparativeActivityService, ComparativeActivityService.class.getSuperclass().getDeclaredMethod("inNewSystem",long.class)).withArguments(111L);
//此處是 mock 一個父類的 protected 方法,其他方法類似
}
}
8.使用白盒測試
Whitebox.setInternalState(someService, "someField", new SomeField());
說明:Whitebox.setInternalState(injectObject,"fieldName", fieldObject)
來爲一個不能直接使用@Mock 註解來注入的屬性注入一個對象
待續
tips
-
打樁失敗;在Test層可以debug看見打樁,但是進入被測函數就發現打樁失敗了
原因:被測試類有一個final字段,並且使用了構造函數傳入了此final字段;
解決:去掉final修飾,將構造函數改爲無參構造函數,使用Java註解進行注入
-
verify校驗失敗:使用eq(obj)校驗的時候,一個是引用地址,另一個是實際對象的值
參考:https://stackoverflow.com/questions/25213897/test-failure-message-in-mockito-arguments-are-different-wanted
原因:eq函數並不能區分是引用地址還是引用的對象值
解決辦法:將eq函數修改爲refEq函數保證校驗的都是對象的值
參考鏈接: https://www.cnblogs.com/Ming8006/p/6297333.html