Jmockit使用
引用单元测试中mock的使用及mock神器jmockit实践中的java单元测试中各种Mock框架对比,就能明白JMockit有多么强大:

JMockit是基于JavaSE5中的java.lang.instrument包开发,内部使用ASM库来动态修改java的字节码,使得java这种静态语言可以想动态脚本语言一样动态设置被Mock对象私有属性,模拟静态、私有方法行为等等,对于手机开发,嵌入式开发等要求代码尽量简洁的情况下,或者对于被测试代码不想做任何修改的前提下,使用JMockit可以轻松搞定很多测试场景。
通过如下方式在maven中添加JMockit的相关依赖:
- <dependency>
- <groupId>com.googlecode.jmockit</groupId>
- <artifactId>jmockit</artifactId>
- <version>1.5</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.googlecode.jmockit</groupId>
- <artifactId>jmockit-coverage</artifactId>
- <version>0.999.24</version>
- <scope>test</scope>
- </dependency>
JMockit有两种Mock方式:基于行为的Mock方式和基于状态的Mock方式:
引用单元测试中mock的使用及mock神器jmockit实践中JMockit API和工具如下:
(1).基于行为的Mock方式:
非常类似与EasyMock和PowerMock的工作原理,基本步骤为:
1.录制方法预期行为。
2.真实调用。
3.验证录制的行为被调用。
通过一个简单的例子来介绍JMockit的基本流程:
要Mock测试的方法如下:
- public class MyObject {
- public String hello(String name){
- return "Hello " + name;
- }
- }
使用JMockit编写的单元测试如下:
- @Mocked //用@Mocked标注的对象,不需要赋值,jmockit自动mock
- MyObject obj;
- @Test
- public void testHello() {
- new NonStrictExpectations() {//录制预期模拟行为
- {
- obj.hello("Zhangsan");
- returns("Hello Zhangsan");
- //也可以使用:result = "Hello Zhangsan";
- }
- };
- assertEquals("Hello Zhangsan", obj.hello("Zhangsan"));//调用测试方法
- new Verifications() {//验证预期Mock行为被调用
- {
- obj.hello("Hello Zhangsan");
- times = 1;
- }
- };
- }
JMockit也可以分类为非局部模拟与局部模拟,区分在于Expectations块是否有参数,有参数的是局部模拟,反之是非局部模拟。
而Expectations块一般由Expectations类和NonStrictExpectations类定义,类似于EasyMock和PowerMock中的Strict Mock和一般性Mock。
用Expectations类定义的,则mock对象在运行时只能按照 Expectations块中定义的顺序依次调用方法,不能多调用也不能少调用,所以可以省略掉Verifications块;
而用NonStrictExpectations类定义的,则没有这些限制,所以如果需要验证,则要添加Verifications块。
上述的例子使用了非局部模拟,下面我们使用局部模拟来改写上面的测试,代码如下:
- @Test
- public void testHello() {
- final MyObject obj = new MyObject();
- new NonStrictExpectations(obj) {//录制预期模拟行为
- {
- obj.hello("Zhangsan");
- returns("Hello Zhangsan");
- //也可以使用:result = "Hello Zhangsan";
- }
- };
- assertEquals("Hello Zhangsan", obj.hello("Zhangsan"));//调用测试方法
- new Verifications() {//验证预期Mock行为被调用
- {
- obj.hello("Hello Zhangsan");
- times = 1;
- }
- };
- }
模拟静态方法:
- @Test
- public void testMockStaticMethod() {
- new NonStrictExpectations(ClassMocked.class) {
- {
- ClassMocked.getDouble(1);//也可以使用参数匹配:ClassMocked.getDouble(anyDouble);
- result = 3;
- }
- };
- assertEquals(3, ClassMocked.getDouble(1));
- new Verifications() {
- {
- ClassMocked.getDouble(1);
- times = 1;
- }
- };
- }
模拟私有方法:
如果ClassMocked类中的getTripleString(int)方法指定调用一个私有的multiply3(int)的方法,我们可以使用如下方式来Mock:
- @Test
- public void testMockPrivateMethod() throws Exception {
- final ClassMocked obj = new ClassMocked();
- new NonStrictExpectations(obj) {
- {
- this.invoke(obj, "multiply3", 1);//如果私有方法是静态的,可以使用:this.invoke(null, "multiply3")
- result = 4;
- }
- };
- String actual = obj.getTripleString(1);
- assertEquals("4", actual);
- new Verifications() {
- {
- this.invoke(obj, "multiply3", 1);
- times = 1;
- }
- };
- }
设置Mock对象私有属性的值:
- public class ClassMocked {
- private String name = "name_init";
- public String getName() {
- return name;
- }
- private static String className="Class3Mocked_init";
- public static String getClassName(){
- return className;
- }
- }
使用JMockit设置私有属性:
- @Test
- public void testMockPrivateProperty() throws IOException {
- final ClassMocked obj = new ClassMocked();
- new NonStrictExpectations(obj) {
- {
- this.setField(obj, "name", "name has bean change!");
- }
- };
- assertEquals("name has bean change!", obj.getName());
- }
使用JMockit设置静态私有属性:
- @Test
- public void testMockPrivateStaticProperty() throws IOException {
- new NonStrictExpectations(Class3Mocked.class) {
- {
- this.setField(ClassMocked.class, "className", "className has bean change!");
- }
- };
- assertEquals("className has bean change!", ClassMocked.getClassName());
- }
- public class StateMocked {
- public static int getDouble(int i){
- return i*2;
- }
- public int getTriple(int i){
- return i*3;
- }
- }
- @Test
- public void testMockNormalMethodContent() throws IOException {
- StateMocked obj = new StateMocked();
- new MockUp<StateMocked>() {//使用MockUp修改被测试方法内部逻辑
- @Mock
- public int getTriple(int i) {
- return i * 30;
- }
- };
- assertEquals(30, obj.getTriple(1));
- assertEquals(60, obj.getTriple(2));
- Mockit.tearDownMocks();//注意:在JMockit1.5之后已经没有Mockit这个类,使用MockUp代替,mockUp和tearDown方法在MockUp类中
- }
- @Test
- public void testGetTriple() {
- new MockUp<StateMocked>() {
- @Mock
- public int getDouble(int i){
- return i*20;
- }
- };
- assertEquals(20, StateMocked.getDouble(1));
- assertEquals(40, StateMocked.getDouble(2));
- }
统计JMockit的单元测试覆盖率:
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.12</version>
- <configuration>
- <argLine>-javaagent:"${settings.localRepository}"/com/googlecode/jmockit/jmockit-coverage/0.999.24/jmockit-coverage-0.999.24.jar</argLine>
- </configuration>
- </plugin>
Jmockit使用的更多相关文章
- JMockit
[TOC] 简介 JMockit是基于JavaSE5中的java.lang.instrument包开发,内部使用ASM库来动态修改java的字节码,使得java这种静态语言可以想动态脚本语言一样动态设 ...
- 使用JUnit4与JMockit进行打桩测试
1. 何为Mock 项目中各个模块,各个类之间会有互相依赖的关系,在单元测试中,我们只关心被测试的单元,对于其依赖的单元并不关心(会有另外针对该单元的测试). 比如,逻辑层A类依赖了数据访问层B类的取 ...
- JMockit使用总结
Jmockit可以做什么 使用JMockit API来mock被依赖的代码,从而进行隔离测试. 类级别整体mock和部分方法重写 实例级别整体mock和部分mock mock静态方法.私有变量.局部方 ...
- jmockit学习
下图为jmockit 类图.在我们编写代码时几乎都会用到Expectations(期望)和Verifications(校验),二者均继承自Invacations. 常会用到的注解有:@Mocked @ ...
- jmockit学习总结
mock类型和实例 从依赖的测试代码调用的方法和构造函数是mock(模拟)的目标. Mocking提供了我们需要的机制,以便将被测试的代码与(一些)依赖关系隔离开来.我们通过声明适当的模拟字段和/或模 ...
- Jmockit之mock特性详解
本文是Jmockit学习过程中,根据官网所列的工具特性进行解读. 1.调用次数约束(Invocation count constraints) 可以通过调用计数约束来指定预期和/或允许匹配给定期望的调 ...
- 单元测试系列:Mock工具Jmockit使用介绍
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6760272.html Mock工具Jm ...
- JMockit常用操作
JMockit常用操作 2017-11-30 转自:http://blog.csdn.net/foreverling/article/details/51234149 目录 1 基本概念 1.1 常 ...
- 单元测试系列之十一:Jmockit之mock特性详解
本文是Jmockit学习过程中,根据官网所列的工具特性进行解读. 1.调用次数约束(Invocation count constraints) 可以通过调用计数约束来指定预期和/或允许匹配给定期望的调 ...
随机推荐
- Jenkins中Jelly基础、超链接、国际化
Jelly基础 参考:https://wiki.jenkins-ci.org/display/JENKINS/Basic+guide+to+Jelly+usage+in+Jenkins UI Samp ...
- 使用Visual Studio下自带的SQL Server Express
软件环境:Windows7(x64) + Visual Studio 2010 + SQL Server Express 2008 1.配置数据库 装VS2010不小心把自带的SQL Server 2 ...
- Python开发程序:简单主机批量管理工具
题目:简单主机批量管理工具 需求: 主机分组 登录后显示主机分组,选择分组后查看主机列表 可批量执行命令.发送文件,结果实时返回 主机用户名密码可以不同 流程图: 说明: ### 作者介绍: * au ...
- Git diff 常见用法
Git diff 用于比较两次修改的差异 1.1 比较工作区与暂存区 git diff 比较的是单个仓库的工作区与暂存区的差别,repo diff是对git diff的封装,用来分别显示各个项目 ...
- Did not find handler method for springMVC资源文件扫描不到---关于spring的那些坑
今天将项目的spring版本升级到4.2.5版本后,登录首页发现资源文件全部访问不到,页面彻底挂掉: 查找原因,后来又查找spring的更新文档后,才确认下来原来是mvc-dispatcher-ser ...
- UE4 性能优化方法(工具篇)
本文依据UE4官方文档以及官方博客等总结而来,可能不全面,后面会陆续添加.内置工具的详细说明请参考官方文档. 游戏帧率很低,或者有卡顿的现象,可能会有很多原因,这时候不要乱猜,比如是不是人物太多了或者 ...
- in-list expansion
in-list expansion也被称作or expansion --针对in后面是常量集合的另外一种处理方法.优化器会把目标sql中in后面的常量集合拆开,把里面的每个常量都提出来形成一个分支,各 ...
- 小试牛刀C#作为脚本语言执行解密
背景 我们知道Unity3d是通过C#脚本语言的形式来实现游戏的逻辑代码编写,同样SCOTT服务器也设置了通过C#脚本来实现游戏逻辑,但是本文并不是想真正分析解密他们的运行机制,只是想通过自己的一个需 ...
- 简介AngularJS中使用factory和service的方法
AngularJS支持使用服务的体系结构“关注点分离”的概念.服务是JavaScript函数,并负责只做一个特定的任务.这也使得他们即维护和测试的单独实体.控制器,过滤器可以调用它们作为需求的基础.服 ...
- 随机采样方法整理与讲解(MCMC、Gibbs Sampling等)
本文是对参考资料中多篇关于sampling的内容进行总结+搬运,方便以后自己翻阅.其实参考资料中的资料写的比我好,大家可以看一下!好东西多分享!PRML的第11章也是sampling,有时间后面写到P ...