在單元測試中需要外部的依賴(我的單元測試是調用了其他系統的方法);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)代碼生成庫