Mockito詳解

1. Mockito:Mockito與JUint不同,並不是單元測試框架。它是用於生成模擬對象或者直接點說,就是“假對象”的工具。使用前需要在方法頂部加註解@RunWith(MockitoJUnitRunner.class),應該如下:

@RunWith(MockitoJUnitRunner.class)
public class ContractMicroServiceImplTest {

需要導入的maven depedency如下:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <scope>test</scope>
    <version>1.9.5</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

2. @Mock:在Mockito中用於創建mock對象,@Mock創建的是全部mock的對象,既在對具體的方法打樁之前,mock對象的所有屬性和方法全被置空(0或者null);與之對應的是@Spy這個註解,@Spy可以創建部分mock的對象,部分mock對象的所有成員方法都會按照原方法的邏輯執行,直到被打樁返回某個具體的值。@Mock和@Spy纔是兩個具有可比性的概念。即,mock對象的所有所有方法都不會進入具體的方法體中,使用場景:ContractMicroServiceImpl類需要調用MicroService類,被測試類是ContractMicroServiceImpl,註解如下:

@Mock
private MicroService microService;

3. @InjectMocks: 在Mockito中用於注入mock對象,也就是創建一個實例,@InjectMocks調用的對象在調用時可以進入到具體的方法體中,使用場景同上,註解如下:

@InjectMocks
private ContractMicroServiceImpl contractMicroService;

4. @Before:和Junit類似,在@Test方法執行前需要執行@Before註解的方法

5. @Test: 單元測試的方法體

6. ReflectionTestUtils.setField:用於InjectMock類中對象的賦值,如下可以理解爲contractMicroService中contractUserName值爲"aaa",其他同理,如下圖:

@Before
public void setup() {
        ReflectionTestUtils.setField(contractMicroService, "contractUserName", "aaa");
        ReflectionTestUtils.setField(contractMicroService, "contractPassword", "bbb");
        ReflectionTestUtils.setField(contractMicroService, "contractIdReference", "contractIdReferences");
        ReflectionTestUtils.setField(contractMicroService, "contractDetailReference", "contractDetailReferences");
}

7. when().thenReturn():用於參數匹配,即根據不同的參數返回不同的結果(切記參數類型、參數值、參數順序都一致),如下:

@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));
}

8. when().thenCallRealMethod(): 用於參數匹配後調用API真實的方法,還可用spy,如下:

@Test
public void real_partial_mock(){
    //通過spy來調用真實的api
    List list = spy(new ArrayList());
    assertEquals(0,list.size());
    A a  = mock(A.class);
    //通過thenCallRealMethod來調用真實的api
    when(a.doSomething(anyInt())).thenCallRealMethod();
    assertEquals(999,a.doSomething(999));
}

9. reset: 用於重置mock,如下:

@Test
public void reset_mock(){
    List list = mock(List.class);
    when(list.size()).thenReturn(10);
    list.add(1);
    assertEquals(10,list.size());
    //重置mock,清除所有的互動和預設
    reset(list);
    assertEquals(0,list.size());
}

10. verify().add(): 用於驗證調用次數,如下:

@Test
public void verify_number_of_invocations(){
    List list = mock(List.class);
    list.add(132);
    list.add(223);
    //驗證是否被調用一次,等效於下面的times(1)
    verify(list).add(1);
    verify(list, times(1)).add(1);
}

 

 

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