Mockito可以做哪些事情

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
  1. 打樁失敗;在Test層可以debug看見打樁,但是進入被測函數就發現打樁失敗了

    原因:被測試類有一個final字段,並且使用了構造函數傳入了此final字段;

    解決:去掉final修飾,將構造函數改爲無參構造函數,使用Java註解進行注入

  2. 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章