随笔

Mockito 简单语法使用

2018-07-24  本文已影响215人  石头1314

使用类库需要在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);
相关语法
    @Test
    public void testMock() {
        List list = mock(List.class);
        list.add("123");
        //当list调用clear()方法时会抛出异常
        doThrow(new RuntimeException()).when(list).clear();
        list.clear();
    }
    @Test
    public void testMock() {
        List list = mock(List.class);
        doReturn("123").when(list).get(anyInt());
        System.out.println(list.get(0));
    }
   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可以使我们的单元测试更加方便便捷。

上一篇 下一篇

猜你喜欢

热点阅读