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)代码生成库

 

 

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