美文网首页随笔
Mockito 简单语法使用

Mockito 简单语法使用

作者: 石头1314 | 来源:发表于2018-07-24 15:11 被阅读215次

    使用类库需要在build.gradle中加入mockito依赖配置:

     testCompile 'org.mockito:mockito-core:2.8.9'
    

    Mock的概念:

    所谓的mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象,以达到两大目的:

     1.验证这个对象的某些方法的调用情况,调用了多少次,参数是什么等等
     2.指定这个对象的某些方法的行为,返回特定的值,或者是执行特定的动作
    

    上面说了Mock的概念,下面开始搬砖,写段代码示例来说明Mockito的一些常用语法使用,代码如下:

    
    /************************************************************
     * Author: ssc
     * Date: 2018/7/20
     * Version: 1.0
     * Description: 人的逻辑判断层
     * History: 
     * <author>  <time>   <version >   <desc>
     ***********************************************************/
    
    public class Person {
        /**
         * 获取该类型性别并进行打印
         *
         * @param type 0代表女生、1代表男生、其他数字提示参数有误
         */
        public void getSex(int type) {
            if (type == 0) {
                printing("女");
            } else if (type == 1) {
                printing("男");
            } else {
                printing("参数有误");
            }
        }
        /**
         * 打印方法
         *
         * @param content
         */
        public void printing(String content) {
            //这里为了简单我们直接控制台输出
            System.out.print(content);
        }
    
        /**
         * 判断类型是否是男人
         *
         * @param type
         * @return
         */
        public boolean isMan(int type) {
            //处理逻辑这里为了方便我们直接进行简单判断
            return type == 1;
        }
    
    }
    
    

    1.如何mock出一个虚假的对象:

    Person person = Mockito.mock(Person.class);
    

    2. 如何验证方法调没调用

    Mockito.verify(person).getSex(...);这句话的作用是,验证person的getSex得到了调用,调用次数为1次。因为这行代码其实是:Mockito.verify(person , Mockito.times(1)).getSex(...)的简写,或者说重载方法,注意其中的Mockito.times(1)。因此,如果你想验证一个对象的某个方法得到了多次调用,只需要将次数传给Mockito.times()就好了。
    Mockito.verify(person, Mockito.times(3)).getSex(...); //验证person的方法getSex(...)得到了三次调用。

    2.1验证方法的调用次数方法有:
    • times(n):方法被调用n次
    • never():没有被调用
    • atLeast(n):至少被调用n次
    • atLeastOnce():至少被调用1次,相当于atLeast(1)
    • atMost():最多被调用n次
      代码演示:
            //执行1次
            verify(person , times(1)).add(...);
            //执行2次
            verify(person , times(2)).add(...);
            verify(person , times(3)).add(...);
            //从不执行, never()等同于times(0)
            verify(person , never()).add(...);
            //验证至少执行1次
            verify(person , atLeastOnce()).add(...);
            //验证至少执行2次
            verify(person , atLeast(2)).add(...);
            //验证最多执行4次
            verify(person , atMost(4)).add(...);
    

    3. 在不关心参数为什么值的情况下,如何通过Mock的语法给出方法所需要的参数对应类型

    比如上面的例子,我们在调用性别后,会走打印方法,这是我们只关心打印方法走没走,而不关心他的参数是什么的时候,我们就要用到Mock的any方法。代码如下:

    Mockito.verify(person).printing(Mockito.anyString());
    

    anyString()表示任何一个字符串都可以。下面我列举一些常用的参数适配方法

    3.1参数适配方法
    • anyString
    • anyInt
    • anyLong
    • anyDouble
    • anyObject 表示任何对象
    • any(clazz)表示任何属于clazz的对象
    • anyCollection
    • anyCollectionOf(clazz)
    • anyList(Map, set)
    • anyListOf(clazz)等等

    4. 指定某个方法的返回值,或者是执行特定的动作。

    4.1指定某个方法的返回值

    Mockito.when(mockObject.targetMethod(args)).thenReturn(desiredReturnValue);
    该方法是执行mockObject.targetMethod()使其返回特定的值desiredReturnValue,据需用我们的person来举例:

    //当调用person的isMan方法,同时传入"0"时,返回true
     (注意这个时候我们调用person.isMan(0);的时候值为true而调用其他数字则为false,
      如果我们忽略数字,传任何值都返回true时,就可以用到我们上面讲的any()参数适配方法)
    Mockito.when(person.isMan(0)).thenReturn(true);
    //当调用person的isMan方法,同时传入"0"时,返回false(注意同上面解释一样)
    Mockito.when(person.isMan(0)).thenReturn(false);
    
    相关语法
    • doThrow(Throwable...):进行异常测试
        @Test
        public void testMock() {
            List list = mock(List.class);
            list.add("123");
            //当list调用clear()方法时会抛出异常
            doThrow(new RuntimeException()).when(list).clear();
            list.clear();
        }
    
    • doReturn():指定返回值
        @Test
        public void testMock() {
            List list = mock(List.class);
            doReturn("123").when(list).get(anyInt());
            System.out.println(list.get(0));
        }
    
    • doNothing() :指定void方法什么都不做
    • doCallRealMethod():指定方法调用内部的真实逻辑
       class Foo {  
            public void doFoo() {
                System.out.println("method doFoo called.");
            }
            public int getCount() {
                return 1;
            }
        }
    
        @Test
        public void testMock() {
            Foo foo = mock(Foo.class);
    
            //什么信息也不会打印, mock对象并不会调用真实逻辑
            foo.doFoo();
    
            //啥也不会打印出来
            doNothing().when(foo).doFoo();
            foo.doFoo();
    
            doCallRealMethod().when(foo).doFoo();
            //这里会调用真实逻辑, 打印出"method doFoo called."信息
            foo.doFoo();
            
            //这里会打印出0
            System.out.println(foo.getCount());
            doCallRealMethod().when(foo).getCount();
            //这里会打印出"1"
            System.out.println(foo.getCount());
        }
    
    4.2执行特定的动作

    在安装中经常用到网络请求数据,而我们在测试时忽略网络请求这块时,就可以用到mock的执行特定的动作:
    Mockito.doAnswer(desiredAnswer).when(mockObject).targetMethod(args);
    传给doAnswer()的是一个Answer对象,我们想要执行什么样的动作,就在这里面实现。如:

    //登录操作:
    /**
     * 网络请求返回
     */
    public interface NetCallback  {
        void onSuccess(Object data);
        void onFailure(int code, String msg);
    }
    /**
     * 网络请求
     * Created by xiaochuang on 4/25/16.
     */
    public class Api{
        public void get(String url, Map<String, String> params, NetworkCallback callback) {
            //网络请求处理操作逻辑,这块忽略写法
            //成功调用callback.onSuccess(data);
            //失败调用callback.onFailure(code,msg);
        }
    }
    ----------------------------------------------------------------------分割线上面是网络请求,下面是doAnswer的使用方法
     Api api = mock(Api.class);
     Mockito.doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            //这里可以获得传给performLogin的参数
            Object[] arguments = invocation.getArguments();
            //callback是第三个参数下标是2
            NetworkCallback callback = (NetworkCallback) arguments[2];
            callback.onFailure(500, "Server error");
            return 500;
        }
     }).when(api).get(anyString(), any(HashMap.class), any(NetworkCallback.class));
     //这时我们调用api.get()方法
     api.get("", null, new NetworkCallback() {
                @Override
                public void onSuccess(Object data) {
    
                }
    
                @Override
                public void onFailure(int code, String msg) {
                    System.out.print(msg);
                }
     });
    //控制台输出Server error。这样我们在测试时,可以忽略网络请求,然后直接判断请求后的操作
    

    有了mock可以使我们的单元测试更加方便便捷。

    相关文章

      网友评论

        本文标题:Mockito 简单语法使用

        本文链接:https://www.haomeiwen.com/subject/dmdspftx.html