在做单元测试的时候,经常会遇到mock类的方法的情景。在写单测过程中,遇到一些问题,比较困惑,便做了一些测试,并得出一个结论:

在mock类的方法时,当符合 (mock参数).equals(实际调用过程中的参数)时,才可以mock成功;当参数为基本类型时,可以使用angLong等。

下面是测试的欢乐时间啦:

首先看测试基础类:

public class Person {
private String name;
private Integer age;
private Person friend;
} public class PersonService { public void showFriendInfo(Person person){
System.out.println("show friend info ...");
showInfo1(new Person("shoren", 22));
showInfo2(person.getFriend());
} public void showInfo1(Person person){
System.out.println("show info1 ...");
} public void showInfo2(Person person){
System.out.println("show info2 ...");
} public void showPersonInfo(Person person){
System.out.println("show person info ...");
showName("shoren");
showName2(person.getName()); } public void showName(String name){
System.out.println("show name1 : " + name);
} public void showName2(String name){
System.out.println("show name2 : " + name);
} }

先看参数为基本类型时:

1. 参数为基本类型时,使用any都可以成功mock。

    @Test
public void testShowPersonInfoUsingAny(){
final Person person = new Person("manyao", 23); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showName", anyString);
Deencapsulation.invoke(personService, "showName2", anyString);
}};
personService.showPersonInfo(person);
}

结果为

show person info ...

2. 参数为基本类型,mock时传入真实的值,且与之前值相等,可以mock成功。

    @Test
public void testShowPersonInfoUsingData(){
final Person person = new Person("manyao", 23); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showName", new String("shoren"));
Deencapsulation.invoke(personService, "showName2", new String("manyao"));
}};
personService.showPersonInfo(person);
}

结果为:

show person info ...

3. 参数为基本类型,mock时传入真实的值,若实际调用值与之不相等,则mock失败。

    @Test
public void testShowPersonInfoUsingData2(){
final Person person = new Person("manyao", 23); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showName", new String("tata"));
Deencapsulation.invoke(personService, "showName2", person.getName());
}};
personService.showPersonInfo(person);
}

结果为

     show person info ...
show name1 : shoren

得出结论:如果参数为基本类型,则mock参数为anyXXX 或者 与实际调用的参数值相等时,可以mkco成功。

再来看参数为复杂类型:

4. 参数为复杂参数时,使用any做类型转换,mock失败。

    @Test
public void testShowFriendUseAny(){
final Person person = new Person("manyao", 23);
person.setFriend(new Person("friend", 24)); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showInfo1", (Person)any);
Deencapsulation.invoke(personService, "showInfo2", (Person)any);
}};
personService.showFriendInfo(person);
}

结果为

     java.lang.IllegalArgumentException: Invalid null value passed as argument 0
at jmockito.PersonServiceTest$4.<init>(PersonServiceTest.java:92)
at jmockito.PersonServiceTest.testShowFriendUseAny(PersonServiceTest.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

5. 参数为复杂参数,mock参数为具体值时,mock参数 equals 实际调用值时,mock成功。

    @Test
public void testShowFriendUseData(){
final Person person = new Person("manyao", 23);
person.setFriend(new Person("friend", 24)); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showInfo1", new Person("shoren", 22));
Deencapsulation.invoke(personService, "showInfo2", person.getFriend());
}};
personService.showFriendInfo(person);
}

结果为

     show friend info ...
show info1 ...

到这里,似乎可以得出这样一个结论,mock内部调用方法时,其mock参数与外部参数的关系,应该与实际执行时,参数的关系一致。即实际调用中,showInfo2的参数是person.getFriend(),

所以,在mock方法showInfo2时,其参数也应该是person.getFriend()。

如果是这样的话,mock方法showInfo1时,又该如何呢?在Person中添加equals方法测试一下。

6. 参数为复杂参数时,(mock参数).equals(实际参数)时,mock成功。

    @Test
public void testShowFriendUseData1(){
final Person person = new Person("manyao", 23);
person.setFriend(new Person("friend", 24)); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showInfo1", new Person("shoren", 22));
Deencapsulation.invoke(personService, "showInfo2", new Person("friend", 24));
}};
personService.showFriendInfo(person);
}

结果为

show friend info ...

7. 参数为复杂参数时,修改equals方法,总是return true时。不论mock参数如何,mock成功.

	 @Test
public void testShowFriendUseData2(){
final Person person = new Person("manyao", 23);
person.setFriend(new Person("friend", 24)); new NonStrictExpectations(personService){{
Deencapsulation.invoke(personService, "showInfo1", new Person());
Deencapsulation.invoke(personService, "showInfo2", new Person());
}};
personService.showFriendInfo(person);
}

结果为

 show friend info ...

综上,我们得出结论:

在mock类的方法时,当符合 (mock参数).equals(实际调用过程中的参数)时,才可以mock成功;当参数为基本类型时,可以使用angLong等。

当然,像这一类的问题,如果要了解清楚,最好还是去阅读源代码。暂时没有时间做这件事。

jmockito模拟方法中参数如何指定的更多相关文章

  1. C#方法中参数ref和out的解析

    一.C#方法中参数类型 有4种参数类型,有时候很难记住它们的不同特征,下图对它们做一个总结,使之更容易比较和对照. 二.C#方法中的参数 1.值参数 使用值参数,通过复制实参的值到形参的方式把数据传递 ...

  2. 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler接口介绍 HandlerMethodArgumen ...

  3. 详解SpringMVC中Controller的方法中参数的工作原理

    Spring MVC中Controller的处理方法的参数可以是Integer,String,自定义对象,ServletRequest,ServletResponse,ModelAndView等等,非 ...

  4. 详解SpringMVC中Controller的方法中参数的工作原理——基于maven

    转自:http://www.tuicool.com/articles/F7byQn 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:ht ...

  5. 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...

  6. 动作方法中 参数,Json

    一.方法中可以出现的参数类 1.HttpServletRequest 2.HttpServletResponse 3.HttpSession 4.Model 二.返回接收json数据 1. 接收,返回 ...

  7. main方法中参数"String[ ] args"详解

    1.在编写完一个有主方法的java文件时,需要在cmd窗口中先编译此java文件(javac xxx.java),然后再运行(java xxx) 其实在运行java xxx的时候如果后面跟着参数用空格 ...

  8. JAVA方法中参数到底是值传递还是引用传递

    当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递? 答:是值传递.Java 语言的参数传递只有值传递.当一个实例对象作为参数被传递到方法中时,参 ...

  9. 将前端请求中的数据绑定到Spring MVC响应方法中参数的四种方法

    一.映射URL绑定的占位符到方法参数 1.方法 使用@PathVariable注解 2.代码示例 a.接收请求方法 @RequestMapping(value = "/deleteInfo/ ...

随机推荐

  1. 麻省理工18年春软件构造课程阅读02“Java基础”

    本文内容来自MIT_6.031_sp18: Software Construction课程的Readings部分,采用CC BY-SA 4.0协议. 由于我们学校(哈工大)大二软件构造课程的大部分素材 ...

  2. 一、Python介绍

    Python 是一门什么样的语言? python是一门动态解释性的强类型定义语言. 编程语言主要从以下几个角度为进行分类,编译型和解释型.静态语言和动态语言.强类型定义语言和弱类型定义语言,每个分类代 ...

  3. scrapy 中日志的使用

    我在后台调试 在后台调试scrapy spider的时候,总是觉得后台命令窗口 打印的东西太多了不便于观察日志,因此需要一个日志文件记录信息,这样以后会 方便查找问题. 分两种方法吧. 1.简单粗暴. ...

  4. Pymongo一些常见需求(陆续补充)

    总结一下最近包括之前遇到的一些pymongo操作的问题. #需求1: 搜索文档数组里边是否存在某元素 数据: data1 = { '_id': xxxxxxxxxxxxxx, 'dataList': ...

  5. AnsibleAPI源码剖析(1)-Runner类的 初始化

    #ansible版本说明:ansible1.9.1 1.简单使用例子 # -*- coding=utf-8 -*- import ansible.runner #################### ...

  6. Navicat远程连接阿里云服务器的mysql

    问题描述: 本机为win10,mysql安装在阿里云(Ubuntu系统)上,本机使用Navicat远程连接mysql,遇到一些坑,求助于阿里云,最终解决,特此记录一下! 安装mysql sudo ap ...

  7. css在盒子中垂直居中和固定居中

    顶部固定居中 <div class="w960 fixed"> 我是固定的 </div> .w960{ width: 960px; margin:0 aut ...

  8. FusionCharts MSBar2D图

    1.页面展示 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...

  9. PowerManager和PowerManager.WakeLock详解

    最近在做项目过程中,有一个LocalPush的需求,需要保持屏幕点亮一段时间,并且在这个时间里,启动Service来执行请求服务器的操作,拿到热点的数据.所以,就找了一下相关的android开源项目. ...

  10. 错误代码: 1054 Unknown column 't.createUsrId' in 'group statement'

    1.错误描述 1 queries executed, 0 success, 1 errors, 0 warnings 查询:select count(t.id),t.`createUserId` fr ...