zoukankan      html  css  js  c++  java
  • Mockito 的使用

    转自:Mockito 中文文档 ( 2.0.26 beta )

    转自:手把手教你 Mockito 的使用

    参数匹配器

    Argument Matcher(参数匹配器)

    Mockito通过equals()方法,来对方法参数进行验证。但是有时候我们需要更加灵活的参数需求,比如,匹配任何的String类型的参数等等。参数匹配器就是一个能够满足这些需求的工具。
    Mockito框架中的Matchers类内建了很多参数匹配器,我们常用的Mockito对象就是继承自Matchers。比如anyInt()匹配任何int类型的参数,anyString()匹配任何字符串...
    复制代码
    @Test 
    public void argumentMatchersTest(){ 
        List<String> mock = mock(List.class); 
        when(mock.get(anyInt())).thenReturn("Hello").thenReturn("World"); 
        String result=mock.get(100)+" "+mock.get(200); 
        verify(mock,times(2)).get(anyInt()); 
        assertEquals("Hello World",result); 
    } 
    复制代码
    首先mock了List接口,然后用迭代的方式模拟了get方法的返回值,这里用了anyInt()参数匹配器来匹配任何的int类型的参数。所以当第一次调用get方法时输入任意参数为100方法返回”Hello”,第二次调用时输入任意参数200返回值”World”。
    这里需要注意:
    如果使用了参数匹配器,那么所有的参数需要由匹配器来提供,否则将会报错。假如我们使用参数匹配器stubbing了mock对象的方法,那么在verify的时候也需要使用它。如:
    复制代码
    @Test 
    public void argumentMatchersTest(){ 
        Map mapMock = mock(Map.class); 
        when(mapMock.put(anyInt(), anyString())).thenReturn("world"); 
        mapMock.put(1, "hello"); 
        verify(mapMock).put(anyInt(), eq("hello")); 
    }   
    复制代码

    在最后的验证时如果只输入字符串”hello”是会报错的,必须使用Matchers类内建的eq方法。如果将anyInt()换成1进行验证也需要用eq(1)。

    自定义匹配器-ArgumentMatcher抽象类

    自定义参数匹配器的时候需要继承ArgumentMatcher抽象类,它实现了Hamcrest框架的Matcher接口,定义了describeTo方法,所以我们只需要实现matches方法在其中定义规则即可。
    下面自定义的参数匹配器是匹配size大小为2的List:

     1 class IsListOfTwoElements extends ArgumentMatcher<List> { 
     2     @ 
     3     public boolean matches(Object list) {  
     4         return ((List) list).size() == 2;  
     5     }  
     6 }  
     7   
     8 @Test  
     9 public void argumentMatchersTest(){  
    10     List mock = mock(List.class);  
    11     when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);  
    12        
    13     mock.addAll(Arrays.asList("one", "two", "three"));  
    14     verify(mock).addAll(argThat(new IsListOfTwoElements()));  
    15 }

    argThat(Matcher<T> matcher)方法用来应用自定义的规则,可以传入任何实现Matcher接口的实现类。上例中在stubbing和verify addAll方法时通过argThat(Matcher<T> matcher),传入了自定义的参数匹配器IsListOfTwoElements用来匹配size大小为2的List。因为例子中传入List的元素为三个,所以测试将失败。

    较复杂的参数匹配将会降低测试代码的可读性。有时实现参数对象的equals()方法是个不错的选择(Mockito默认使用equals()方法进行参数匹配),它可以使测试代码更为整洁。另外,有些场景使用参数捕获器(ArgumentCaptor)要比自定义参数匹配器更加合适。 

    如何捕获 mock 方法的调用参数

    Mockito以java代码风格的形式来验证参数值 : 即通过使用equals()函数。这也是我们推荐用于参数匹配的方式,因为这样会使得测试代码更简单、简洁。在某些情况下,当验证交互之后要检测真实的参数值时这将变得有用。例如 :

     1 @Test
     2 public void captureNonGenericArgument() {
     3   UserDao userDao = Mockito.mock(UserDao.class);
     4   UserService  userService = new UserService(userDao);
     5  
     6   userService.saveUser(new User(null, "Yanbin"));
     7   
     8   ArgumentCaptor<User> argumentCaptor = ArgumentCaptor.forClass(User.class);
     9   verify(userDao, times(1)).save(argumentCaptor.capture());
    10  
    11    assertEquals("Yanbin", argumentCaptor.getValue().name);
    12    assertEquals("Chicago", argumentCator.getValue().city); //可断言捕获参数的更多特征

    从面对被捕获参数 argumentCaptor.getValue() 的断言可看出它比 argThat() 的优势,argThat() 无法告诉我们不匹配的细节

    警告 : 我们建议使用没有测试桩的ArgumentCaptor来验证,因为使用含有测试桩的ArgumentCaptor会降低测试代码的可读性,因为captor是在断言代码块之外创建的。另一个好处是它可以降低本地化的缺点,因为如果测试桩函数没有被调用,那么参数就不会被捕获。总之,ArgumentCaptor与自定义的参数匹配器相关(可以查看ArgumentMatcher类的文档 )。这两种技术都能用于检测外部传递到Mock对象的参数。然而,使用ArgumentCaptor在以下的情况下更合适 :

    • 自定义不能被重用的参数匹配器
    • 你仅需要断言参数值

    我们同样可以在打桩的时候捕获参数,如

    1 ArgumentCaptor<User> argumentCaptor = argumentCaptor.forClass(User.class);
    2 when(userDao.findUserLike(argumentCaptor.capture)).thenReturn(Mockito.mock(User.class));
    3  
    4 assertEquals("Yanbin", argumentCaptor.getValue().name);

     不能以这种方式在打桩的时候捕获参数:

    1 when(userDao.findUserLike(argumentCaptor.capture)).thenReturn(getUser(argumentCaptor.getValue()));

    否则会报错:

    出错位置在打桩的地方。记住打桩并不等于异步调用,它返回的是个固定值!

  • 相关阅读:
    第07节-开源蓝牙协议BTStack框架代码阅读(上)
    第06节-开源蓝牙协议BTStack框架分析
    第05节-BLE协议物理层(PHY)
    第04节-BLE协议抓包演示
    第03节-BLE协议各层数据格式概述
    【重点声明】此系列仅用于工作和学习,禁止用于非法攻击。一切遵守《网络安全法》
    海外信息安全资源
    从浏览器攻击思考入门的问题。
    攻击载荷免杀技术
    聊聊NTLM认证协议
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/10595138.html
Copyright © 2011-2022 走看看