Mockito小記

在單元測試中需要外部的依賴(我的單元測試是調用了其他系統的方法);mockito 主要是用來模擬外部依賴接口的返回。

通過stub打樁,通過方法名及其參數定位測試樁然後返回預期的值。

Mockito.when消費的是方法的返回值,對方法內部不感知。


Mockito.mock()與@MockBean ,@Mock用法(實際只用過@MockBean)

  • Mockito.mock()

允許創建類或接口的模擬對象;然後使用mock來存儲其方法的返回值,並驗證是否被調用。

public void queryLastOrder1(){
            GenericRequest genericRequest = GenericRequest.builder()
                        .latitude(22.9999)
                        .longitude(132.999)
                        .userId("passager1")
                        .build();
            RouteService mock = Mockito.mock(RouteService.class);
            Mockito.when(mock.queryRouteInfo("route1")).thenReturn(toBuildRoute());
            QueryRouteInfoParam queryRouteInfoParam = QueryRouteInfoParam.builder()
                        .tripId("2b39fffe9e6a4210979d64b57eeab002")
                        .latitude(genericRequest.getLatitude())
                        .longitude(genericRequest.getLongitude())
                        .build();
            Mockito.when(routeService.queryRouteForOrder(queryRouteInfoParam)).thenReturn(toBuildRoute());
            OrderResponse orderResponse = orderQueryService.queryLastOrder(genericRequest);
            Assert.assertNotNull(orderResponse);
            Assert.assertEquals("2133664421132098881", orderResponse.getOrderId().toString());
            //是否被調用
            Mockito.verify(mock).queryRouteForOrder(queryRouteInfoParam);
      }
  • @Mock(例子是找的)

是Mockito.mock()的簡寫,不過需要Mockito註解才能使用;可以通過使用MockitoJUnitRunner來運行測試或者顯示調用MockitoAnnotations.initMocks()方法來實現。

@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {
     
    @Mock
    UserRepository mockRepository;
     
    @Test
    public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
        Mockito.when(mockRepository.count()).thenReturn(123L);
 
        long userCount = mockRepository.count();
 
        Assert.assertEquals(123L, userCount);
        Mockito.verify(mockRepository).count();
    }
}

與{@InjectMocks:創建一個實例,其餘用@Mock(或@Spy)註解創建的mock將被注入到用該實例中}一起用

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
 
    @Mock
    private MyRepository myRepository;
 
    @InjectMocks
    private MyService myService;
 
    @Test
    public void testInjectMocks() {
        System.out.println(myService.getMyRepository().getClass());
    }
}

MyService 被標記了 @InjectMocks,在 setUp方法中 執行 MockitoAnnotations.initMocks(this); 的時候,會將標記了 @Mock 或 @Spy 的屬性注入到 service 中。MyService 裏面的 MyRepository 完全被Mock實例替換,所有的調用都是針對Mock生成類的

 

  • @MockBean

可以使用@MockBean將模擬對象添加到Spring應用程序上下文中。mock將替換應用程序上下文中任何相同類型的現有bean。 如果沒有定義相同類型的bean,則會添加一個新bean。此註釋在集成測試中很有用,在集成測試中需要模擬特定的bean(例如,外部服務)。 要使用此批註,我們必須使用@RunWith(SpringRunner.class)來運行測試

​
@MockBean
      private RouteService routeService;


@Test
​public void queryLastOrder(){
GenericRequest genericRequest = GenericRequest.builder()
                        .latitude(22.9999)
                        .longitude(132.999)
                        .userId("passager1")
                        .build();
            
            Mockito.when(routeService.queryRouteInfo("route1")).thenReturn(toBuildRoute());
            QueryRouteInfoParam queryRouteInfoParam = QueryRouteInfoParam.builder()
                        .tripId("2b39fffe9e6a4210979d64b57eeab002")
                        .latitude(genericRequest.getLatitude())
                        .longitude(genericRequest.getLongitude())
                        .build();
       //返回模擬數據    
 Mockito.when(routeService.queryRouteForOrder(queryRouteInfoParam)).thenReturn(toBuildRoute());
            //queryLastOrder方法中調用了兩個外部方法(routeService.queryRouteInfo;routeService.queryRouteForOrder)
            OrderResponse orderResponse = orderQueryService.queryLastOrder(genericRequest);
            Assert.assertNotNull(orderResponse);
            Assert.assertEquals("2133664421132098881", orderResponse.getOrderId().toString());

}

 

--Mockito.verify()判斷是否被調用


Mockito的原理是動態代理(還在學習中)

 動態代理:JDK和CGLIB(Code Generation Library)代碼生成庫

 

 

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