Mockito 简单语法使用

使用类库需要在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可以使我们的单元测试更加方便便捷。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容