`

JMockit 使用

 
阅读更多

 

JMockit 使用 
1.使用介绍 
传统mock方法的限制: 
JDK Proxy必须实现接口 
Cglib Proxy的class和方法不能是final限定的 
对于静态方法无能为力 
对非public方法无能为力,或者需要花比较大的代价进行反射处理 
比较依赖于Ioc机制,对于new或工厂类管理的bean无法进行有效的测试 
JMockit优点 
JMockit项目基于 Java 5 SE 的 java.lang.instrument 机制,内部使用 ASM 库来修改Java的Bytecode,是一个能帮我们解决以上问题的轻量级框架,它允许你动态的改变已有的方法,这主要基于java 1.5的Instrumentation框架,允许你重定义private,static and final方法,甚至是no-arg constructors都能够并轻易的重定义,这样便可以使得JMockit能够适应几乎所有的设计。 
使用mock的场景 
真实对象有着不确定的行为 
真实对象很难创建 
真实对象的行为很难触发 
真实对象响应缓慢 
真实对象是用户界面 
真实对象使用了回调机制 
真实对象尚未存在 
而对应的mock具有下面的功能 
替换远程对象,如ESB、WEB Service对象等 
替换复杂的对象 
方便模块化开发 
2.JMockit原理 
JMockit是依赖JDK提供的instrument机制及ASM来实现其功能的,基本原理是这样的: 
在JDK装入类的时候,由于我们设置也-javaagent,JDK会查看这个jar包的/META-INF/MANIFEST.MF文件,找到Premain-Class并加载这个类,然后调用这个类的premain方法将Instrument实现设置进去,然后JMockit就可以在类加载的时候做transformer,在做transformer的时候会通过ASM来动态改变字节码。 
如果大家想有更深入的也解请在这里下载源代码。 

3.JMockit运行环境要求 
对于JDK5之后版本,不用设置;对于JDK5,需要配置jvm参数-javaagent:jmockit.jar 
在 windows-perferences-java-installedJRES-default vm argument 中设置 
-javaagent:D:\xx\xx\jmockit.jar 

4.JMockit使用实例 
关键词:如何mock一个类的方法、Expectations 
源类清单 
Java代码  收藏代码
  1. public class DateUtil {  
  2.   
  3.     private int type;  
  4.   
  5.     public static final String getCurrentDateStr() {  
  6.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  7.         return sdf.format(DateUtil.now());  
  8.     }  
  9.   
  10.     public static final String getCurrentDateStrByFormatType(int type) {  
  11.         if (type == 1) {  
  12.             SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");  
  13.             return sdf.format(DateUtil.now());  
  14.         } else {  
  15.             return DateUtil.getCurrentDateStr();  
  16.         }  
  17.     }  
  18.   
  19.     public static final Date now() {  
  20.         return new Date();  
  21.     }  
  22.   
  23.     public int getType() {  
  24.         return type;  
  25.     }  
  26.   
  27.     public void setType(int type) {  
  28.         this.type = type;  
  29.     }  
  30.   
  31. }  

单元测试类清单1 
Java代码  收藏代码
  1. public class DateUtilTest {  
  2.   
  3.     /** 
  4.      * Mock某个类方法 
  5.      */  
  6.     @Test  
  7.     public void testGetCurrentDateStr() {  
  8.         //DateUtil.class,要Mock的类  
  9.         new Expectations(DateUtil.class) {  
  10.             {  
  11.               //要Mock的方法now,其他方法DateUtil.class  
  12.                 DateUtil.now();  
  13.               //期望方法返回的结果  
  14.                 result = mockDate();  
  15.             }  
  16.         };  
  17.         Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());  
  18.     }  
  19.   
  20.     /** 
  21.      * Mock 某个类方法根据不同参数返回不同值 
  22.      */  
  23.     @Test  
  24.     public void testGetCurrentDateStrByFormatType() {  
  25.         new Expectations(DateUtil.class) {  
  26.             {  
  27.                 DateUtil.getCurrentDateStrByFormatType(anyInt);  
  28.                 result = new Delegate() {  
  29.                     public String getCurrentDateStrByFormatType(int type) {  
  30.                         if (type == 1) {  
  31.                             return "2010/07/22 15:52:55";  
  32.                         } else {  
  33.                             return "2010-07-22 15:52:55";  
  34.                         }  
  35.                     }  
  36.                 };  
  37.             }  
  38.         };  
  39.         Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStrByFormatType(2));  
  40.   
  41.     }  
  42.   
  43.     public static Date mockDate() {  
  44.         Calendar c = Calendar.getInstance();  
  45.         c.set(2010622155255);  
  46.         return c.getTime();  
  47.     }  
  48.   
  49. }  

小结 
Expectations:一个Expectations块是给定测试方法中将会涉及到的mock项中,预期将要被调用的方法或构造函数。一个Expectations可以包含多个预期的要执行方法(mock),但不必包含所有预期会被调用的方法。在Expectations中;除了可以指定预期的方法外,还可以指定方法的参数的精确值或约束行为(满足某个断言);同时Expectations中还可以指定该方法预期的返回值(如果有)或预期抛出的异常。Expectations(.class){}这种方式只会模拟区域中包含的方法,这个类的其它方法将按照正常的业务逻辑运行,上面的例子,定义了一个mock类DateUtil,同时在Expectation中定义了预期会被调用的方法now,以及now方法的返回值,这种方式还有种等价实现方式,使用@Mocked标签 
Java代码  收藏代码
  1. @Test  
  2.     public void testGetCurrentDateStr(@Mocked(methods="now")DateUtil dateUtil) {  
  3.         //DateUtil.class,要Mock的类  
  4.         new Expectations() {  
  5.             {  
  6.                 //声明要Mock的方法(注:其它方法按照正常的业务逻辑运行)  
  7.                 DateUtil.now();  
  8.                 //期望方法返回的结果  
  9.                 result = mockDate();  
  10.             }  
  11.         };  
  12.         Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());  
  13.     }  
  14.       

case-2 
关键词:service dao @Mocked 
源类清单 
Java代码  收藏代码
  1. public interface P4psettleDayService {  
  2.     public List<DaySyncVerifyDO> getDaySyncVerifyNotSuccessList();  
  3.   
  4.     public void updataStatusById(Integer id,String status);  
  5. }  

单元测试类清单 
Java代码  收藏代码
  1. @TestCaseInfo(contextKey = "P4PSettleServicesLocator", defaultRollBack = false)  
  2. public class P4psettleDayServiceImplTest extends BaseTestCase {  
  3.   
  4.     private P4psettleDayService p4psettleDayService;  
  5.   
  6.     public void setP4psettleDayService(P4psettleDayService p4psettleDayService) {  
  7.         this.p4psettleDayService = p4psettleDayService;  
  8.     }  
  9.   
  10.     /** 
  11.      * 此例子仅为说明如何Mock我们现有service或dao的部分方法 
  12.      */  
  13.     @Test  
  14.     public void testUpdataStatusById() {  
  15.             new MockUp<P4psettleDayServiceImpl>(){  
  16.               @Mock  
  17.               public List<DaySyncVerifyDO> getDaySyncVerifyNotSuccessList(){  
  18.                 List<DaySyncVerifyDO> list = new ArrayList<DaySyncVerifyDO>();  
  19.                 DaySyncVerifyDO mockDO = new DaySyncVerifyDO();  
  20.                 mockDO.setId(111111);  
  21.                 list.add(mockDO);  
  22.                 return list;  
  23.               }  
  24.              };  
  25.         //这里将返回我们mock的数据  
  26.         List<DaySyncVerifyDO> list = p4psettleDayService  
  27.                 .getDaySyncVerifyNotSuccessList();  
  28.         if (list != null && list.size() > 0) {  
  29.             for (DaySyncVerifyDO item : list) {  
  30.                 //这里执行原有的方法  
  31.                 p4psettleDayService.updataStatusById(item.getId(),  
  32.                         DayEnum.DAYSYNCVERIFY_STATUS_SUCCESS.getValue());  
  33.             }  
  34.         }  
  35.     }  
  36.   
  37. }  
  38.    

小结 
上面单元测试代码没有实际意义,只是说明如果我们希望mock spring注入的service或dao的一个或多个方法,就可采用上述方式 
case-3 
关键词:mock private方法 invoke 
源类清单 
还是第一个例子,Now方法是私有的 
Java代码  收藏代码
  1. public class DateUtil {  
  2.     ......  
  3.     private static final Date now() {  
  4.         return new Date();  
  5.     }  
  6.     ......  
  7.   
  8. }  
  9.       

单元测试类清单 
Java代码  收藏代码
  1. public class DateUtilTest {  
  2.     /** 
  3.      * Mock某个类私有方法 
  4.      */  
  5.     @Test  
  6.     public void testGetCurrentDateStr() {  
  7.         //DateUtil.class,要Mock的类  
  8.         new Expectations(DateUtil.class) {  
  9.             {  
  10.               //执行DateUtil的now方法  
  11.                 invoke(DateUtil.class,"now");  
  12.               //期望方法返回的结果  
  13.                 result = mockDate();  
  14.             }  
  15.         };  
  16.         Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());  
  17.     }  
  18.       

小结 
mock 某个类的私有方法,用invoke(mock的类或实例,方法名,方法的参数列表) 
case-4 
关键词:Verifications 想验证被Mock的类的某个方法是否被调用 
单元测试类清单 
Java代码  收藏代码
  1. /** 
  2.  * 演示验证被Mock的类的某个方法是否被调用 
  3.  * 
  4.  * @author LeiSir 
  5.  */  
  6. public class ServiceTest {  
  7.   
  8.     @Mocked  
  9.     Remote remote;  
  10.   
  11.     @Test  
  12.     public void testDoFuncYes() {  
  13.         Service service = new Service();  
  14.         service.doFunc(true1);  
  15.         new Verifications() {  
  16.             {  
  17.                 remote.doSomething(anyInt);//表示这个方法会被执行  
  18.                 //remote.doSomething(1);//表示这个方法会被执行,而且参数是1;在当前case,会通过  
  19.                 //remote.doSomething(2);//表示这个方法会被执行,而且参数是2;在当前case,这个会不被通过  
  20.   
  21.             }  
  22.         };  
  23.   
  24.     }  
  25.   
  26.     @Test  
  27.     public void testDoFuncNo() {  
  28.         Service service = new Service();  
  29.         service.doFunc(false1);  
  30.         new Verifications() {  
  31.             {  
  32.                 remote.doSomething(anyInt);  
  33.                 times = 0;//调用次数,0表示上面方法不会被调用  
  34.             }  
  35.         };  
  36.     }  
  37.   
  38.     private static class Remote {  
  39.         public void doSomething(int a) {  
  40.         }  
  41.     }  
  42.   
  43.     private static class Service {  
  44.   
  45.         private Remote remote = new Remote();  
  46.   
  47.         public void doFunc(boolean flag, int a) {  
  48.             if (flag) {  
  49.                 remote.doSomething(a);  
  50.             }  
  51.         }  
  52.     }  
  53.   
  54. }  

小结 
有时候我们想验证某个类的方法是否被正确调用的时候,上述Verifications就派上用场了 
分享到:
评论

相关推荐

    jmockit使用例子

    jmockit使用例子,包括两种调用方式,可以改变静态方法

    jmockit_sample:jmockit 使用示例代码和说明

    使用mock测试的几点好处: a、能够帮助我们解耦设计,即以接口设计为中心。 b、在使用其他对象的...使用jmockit,不要使用jre,要用jdk,否则,可能出现比如java.lang.NoClassDefFoundError: org.junit.runner.Runner

    JMockit教程.pdf

    正如其名,在单元测试时,CUT(Code Under Test ,被测试代码)可能会依赖其他代码,可以使用JMockit API来mock被依赖的代码,从而进行隔离测试。 JMockit有两套API,mock API用来进行mock测试;mock-up API用来...

    jmockit框架所使用jar包

    jmockit框架所使用jar包,在写单元测试的过程中我们会发现需要测试的类有很多依赖,这些依赖的类或者资源又会有依赖,导致在单元测试代码里无法完成构建,我们应对的方法是Mock。简单的说就是模拟这些需要构建的类...

    Step By Step写测试(书签版).pdf

    4 JMockit使用 4.1 jmockit的优点 4.1.1 传统mock方法的限制: 4.1.2 使用mock的场景 4.1.3 运行jmockit测试 4.2 基于状态的jmockit测试 4.2.1 方法一:使用@MockClass和 @UsingMocksAndStubs 4.2.2 方法二:使用...

    jmockit总结

    jmockit资料,关于jmockit的具体使用方式,以及不同方法的详解。

    使用JMockit编写java单元测试

    之前《有效使用Mock编写java单元测试》一文中层介绍过使用EasyMock和PowerMock来编写java单元测试,今天介绍一个更加强大的工具——JMockit。引用单元测试中mock的使用及mock神器jmockit实践中的java单元测试中各种...

    jmockit1:用于集成测试,模拟,伪造和代码覆盖的高级Java库

    JMockit 1.x发行版的代码库-- 如何建立专案: 使用JDK 1.8或更高版本 使用Maven 3.6.0或更高版本; 以下是顶级模块: main / pom.xml:构建jmockit-1.n.jar,运行JUnit 4和TestNG测试套件 coverageTests / pom.xml...

    jpa-lucene-spring-demo:使用JPA,Lucene,Spring,DBUnit和JMockit的演示项目-持久并搜索简单的Book数据

    有2个测试类-一个使用JUnit和JMockit的简单单元测试,另一个使用DBUnit的测试。 DBUnit测试是一个很好的例子,可以了解它是如何工作的-它会填充内存中的HSQL数据库,然后使用Lucene查询其中的数据。 该示例很简单...

    jutf:Java单元测试框架(Warp H2Mockitojmockit工具,使Java应用程序更好)

    使用mockito / jmockit来模拟界面 实用程序模拟get / set / construct / tostring H2内存测试数据库工具 日志消息检查器 jutf-Spring(spring依赖版本) 使用mockito / jmockit来模拟界面 实用程序模拟get / set ...

    Springboot 3中,使用jacoco插件生成单元测试覆盖率报告

    springboot3 + jdk17 + maven + jmockit

    jmockit-examples:模拟一些麻烦的旧代码模式的示例

    JMockit示例是一个令人印象深刻的模拟库,但它也相当复杂,在使用大型旧代码库时可能会令人生畏。 在这个项目中,我正在记录解决方案,这些解决方案旨在模拟遇到的一些麻烦的代码模式。 我已经将它们归结为基本知识...

    SpringWebApplication:使用 gradle 的规范 Spring Web 应用程序。 包括 CSSJS 支持

    #SpringWeb应用程序该项目旨在成为 Spring MVC 中简单 Web 应用程序的规范示例。 这里没有服务或 dao 层,只有具有 CSS/JS 表示层支持的 JSP 和控制器前端。 该项目展示了以下内容: 使用...JMockit 进行单元测试启动服

    JavaPOC:概念证明

    使用“严格”时,预期代码行为的顺序非常重要。 模拟系统时间是一项艰巨的任务。 我花了很多研究才能了解如何在JMockit中仅模拟一个方法System.currentTimeMillis() 。 我陷入的陷阱是模拟了整个System.class ,...

    Explorando-Marte

    JMockit用于模拟和检查单元测试。设计由于该应用程序只是一个客户端,因此我不想创建一个域层,而只创建一个表示层和一个应用程序层: 看法表示层,负责为用户提供命令行界面,并实现有助于解释来自控制台的命令以...

Global site tag (gtag.js) - Google Analytics