JMockit使用时,建议使用Expectations{}块来录制行为,这样mock对象在运行时必须 依据Expectations块中定义的顺序依次调用方法,不能多调用也不能少调用,可以省略掉Verifications块。一旦多调用或则少调用,那么测试就不会通过,这样可以清晰的把握单元测试每一步、每一次执行的过程。
       但是,测试的方法中如果存在线程的调用来执行录制行为,很多情况用Expectations{}块测试都不会通过,而使用NonStrictExpectations{}块来录制就不会有问题。

示例:
测试目标:

package org.zero.jmockit;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;class OtherVO {private String value;public String getValue() {return value;}public void setValue(String value) {this.value = value;}
}public class Work {private OtherVO otherVO;private ExecutorService executor = Executors.newFixedThreadPool(4);public void task() {executor.execute(new Runnable() {public void run() {otherVO.getValue();}});}
}

测试文件:

package org.zero.jmockit;import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;
import mockit.integration.junit4.JMockit;import org.junit.Test;
import org.junit.runner.RunWith;@RunWith(JMockit.class)
public class WorkTest {@Tested@MockedWork work;@Testpublic void testTask() {final OtherVO otherVO = new OtherVO();new Expectations(OtherVO.class) { // mock OtherVO的行为{otherVO.getValue();result = "zero";}};new Expectations() {{Deencapsulation.setField(work, "otherVO", otherVO);}};// --- 通过以上方式可以将mock出来的otherVO设置到work中,当然可以采取其它简便方式work.task();}
}

运行测试,会发现测试不通过,会抛出一下异常:

mockit.internal.MissingInvocation: Missing 1 invocation to:
org.zero.jmockit.OtherVO#getValue()on mock instance: org.zero.jmockit.OtherVO@3419866cat org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: Missing invocationsat org.zero.jmockit.OtherVO.getValue(Work.java)at org.zero.jmockit.WorkTest$1.<init>(WorkTest.java:23)at org.zero.jmockit.WorkTest.testTask(WorkTest.java:21)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at java.lang.reflect.Method.invoke(Method.java:497)... 6 more

明明调用了work.task(),task()里会调用getValue()方法,但是怎么会报Missing invocations错误(少调了OtherVO#getValue()方法)。为什么呢?原因在于线程的调用,executor.execute()只是通知线程去执行runnable,runnable中任务的执行需要JVM去调度,至于什么时候去执行,可能发生在整个testTask()结束后,而Expectations{}检测到录制行为在testTask()结束前依然没被回放,因此就会报错。

怎么解决呢?
       在work.task()调用后sleep()一段时间,以等runnable中任务被执行了再结束testTask()不就可以了么。这也是一个办法。但最好的解决方式是mock executor的execute()方法,让它不执行runnable.start(),而是执行runnable.run(),如下:

@RunWith(JMockit.class)
public class WorkTest {@Tested@MockedWork work;private ExecutorService executor;@Beforepublic void initThread() {executor = new MockUp<ThreadPoolExecutor>() {@Mockpublic void execute(Runnable command) {command.run();}}.getMockInstance();}@Testpublic void testTask() {final OtherVO otherVO = new OtherVO();new Expectations(OtherVO.class) { // mock OtherVO的行为{otherVO.getValue();result = "zero";}};new Expectations() {{Deencapsulation.setField(work, "otherVO", otherVO);}};// --- 通过以上方式可以将mock出来的otherVO设置到work中,当然可以采取其它简便方式new Expectations() {{Deencapsulation.setField(work, "executor", executor);// --- 将mock出来executor设置到work中}};work.task();}
}

另一种简单方式:

@RunWith(JMockit.class)
public class WorkTest {@Tested@MockedWork work;@Testpublic void testTask() {final OtherVO otherVO = new OtherVO();new Expectations(OtherVO.class) { // mock OtherVO的行为{otherVO.getValue();result = "zero";}};new Expectations() {{Deencapsulation.setField(work, "otherVO", otherVO);}};// --- 通过以上方式可以将mock出来的otherVO设置到work中,当然可以采取其它简便方式new MockUp<ThreadPoolExecutor>() {@Mockpublic void execute(Runnable command) {command.run();}};work.task();}
}

JMockit简单使用(二)相关推荐

  1. autocad2007二维图画法_cad怎样绘制简单的二维图形

    CAD绘制二维图形非常的简单,大家经常用它来画图,下面是学习啦小编带来关于cad怎样绘制简单的二维图形的内容,希望可以让大家有所收获! cad绘制简单二维图形的方法 1.绘图菜单绘图菜单是绘制图形最基 ...

  2. Keras之ML~P:基于Keras中建立的简单的二分类问题的神经网络模型(根据200个数据样本预测新的5个样本)——概率预测

    Keras之ML~P:基于Keras中建立的简单的二分类问题的神经网络模型(根据200个数据样本预测新的5个样本)--概率预测 目录 输出结果 核心代码 输出结果 核心代码 # -*- coding: ...

  3. Keras之ML~P:基于Keras中建立的简单的二分类问题的神经网络模型(根据200个数据样本预测新的5+1个样本)——类别预测

    Keras之ML~P:基于Keras中建立的简单的二分类问题的神经网络模型(根据200个数据样本预测新的5+1个样本)--类别预测 目录 输出结果 核心代码 输出结果 核心代码 # -*- codin ...

  4. Redis简单案例(二) 网站最近的访问用户

    原文:Redis简单案例(二) 网站最近的访问用户 我们有时会在网站中看到最后的访问用户.最近的活跃用户等等诸如此类的一些信息.本文就以最后的访问用户为例, 用Redis来实现这个小功能.在这之前,我 ...

  5. java爬虫之基于httpclient的简单Demo(二)

    转载自 java爬虫之基于httpclient的简单Demo(二) 延续demo1的 java爬虫的2种爬取方式(HTTP||Socket)简单Demo(一),demo2出炉啦,大家想学爬虫都可以从这 ...

  6. WebSocket简单使用(二) - 客户端

    WebSocket简单使用(二) - 客户端 原文 http://www.oseye.net/user/kevin/blog/79 关于WebSocket我打算分如下几篇博文来探探路: WebSock ...

  7. iOS开发UI篇—Quartz2D简单使用(二)

    iOS开发UI篇-Quartz2D简单使用(二) 一.画文字 代码: // // YYtextview.m // 04-写文字 // // Created by 孔医己 on 14-6-10. // ...

  8. Akka Remote Actor_简单示例二

    2019独角兽企业重金招聘Python工程师标准>>> Akka Remote Actor_简单示例二 在上一篇文章中,http://my.oschina.net/xinxingeg ...

  9. mysql使用简单教程_Mysql使用简单教程(二)_MySQL

    接上文Linux系统下Mysql使用简单教程(一) 字段参数以"(字段名1 数据类型1,字段名2 数据类型2,......)"的形式构建. 关于mysql常用的数据类型,一下是比较 ...

最新文章

  1. GAAFET与FinFET架构
  2. HashTable和HashMap的区别详解
  3. 取得cpu核心序号_cpu的性能指标有哪些?
  4. C#编码简单性之代码篇(如何编写简短的C#代码,随时更新)
  5. C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密
  6. 1.Spring Cloud Alibaba教程:简介
  7. 神策数据上线 IPTV Demo ,三大价值助力数据驱动
  8. HBase 2.X版本的元数据修复及一种数据迁移方式
  9. java基础----集合之Map集合基本方法的使用以及遍历
  10. 【插件开发】—— 13 GEF双击模型事件
  11. 【BZOJ】3575: [Hnoi2014]道路堵塞
  12. Android Track的play流程(三十二)
  13. python制作网页挂机_python使用ip代理抓取网页
  14. Python处理Excel数据-pandas篇
  15. 高斯消去法(Gauss)的python实现
  16. 手把手教你搭建属于自己的技术博客
  17. WiFi模块硬件兼容封装尺寸三:LGA-44/12*12mm
  18. 景区厕所污水处理有哪些问题?
  19. JGG:肠道菌群与COVID-19重症风险密切关联
  20. “耀星计划”之华为信用钱包,覆盖HMS生态多领域

热门文章

  1. 通过注册表设置VMware Horizon View Client SSL配置
  2. C语言简单实现文件传输
  3. python图像处理教程,【图像处理】使用OpenCV+Python进行图像处理入门教程(二)...
  4. Windows Embedded Compact 7可定制化互联网电视
  5. 第六讲 Linux字符设备驱动1
  6. 计算机二级网上哪里学,计算机二级学习网址
  7. linux如何开放端口和关闭端口
  8. 2011年成都信息工程学院第二季极客大挑战逆向第二题Crackwho破文
  9. 小忽视大问题:4.8通过 Apple 登录
  10. gradle编译错误:Unfortunately you can‘t have non-Gradle Java modules and Android-Gradle modules in one