公司对开发人员的单元测试要求比较高,要求分支覆盖率、行覆盖率等要达到60%以上等等。项目中已经集成了jmockit这个功能强大的mock框架,学会使用这个框架势在必行。从第一次写一点不会,到完全可以应付工作要求,期间踩了好多坑,学到了不少东西。下面简单总结一下jmockit这个框架的使用,重点介绍MockUp的使用,因为项目中都采用此种方式模拟方法。

一、框架集成

添加maven依赖

org.jmockit

jmockit

1.16

test

junit

junit

4.12

二、@Mocked模拟方式介绍

@Mocked模拟,由录制、回放、验证三步骤完成,是对某个类的所有实例的所有方法进行完整的模拟方式。

/*** 被测试类*/

public classApp {publicString say() {return "Hello World";

}publicString say2(){return "Hello World 2";

}public staticString staticSay() {return "Still hello world";

}

}

/*** 测试类*/

public classAppTest {/*** 针对类及所有实例的的整体模拟,未写录制的方法默认返回0,null等*/@Mocked

App app;

@Testpublic voidtestSay() {//录制,定义被模拟的方法的返回值,可以录制多个行为,写在一个大括号里也可以,多个大括号隔开也可以

newExpectations() {{

app.say();

result= "say";

}};//回放,调用模拟的方法

System.out.println(app.say()); //say

System.out.println(new App().say()); //say

System.out.println(App.staticSay()); //null//验证

newVerifications() {{//验证say模拟方法被调用,且调用了2次

app.say();

times= 2;//验证staticSay模拟方法被调用,且调用了1次

App.staticSay();

times= 1;

}};

}

}

三、@Injectable模拟方式介绍

@Injectable和@Mocked的方式很像,区别是@Injectable仅仅对当前实例进行模拟。

/*** 测试类*/

public classAppTest001 {/*** 仅针对当前实例的整体模拟*/@Injectable

App app;

@Testpublic voidtestSay() {//录制

newExpectations() {{

app.say();

result= "say";

}};//回放

System.out.println(app.say()); //say,模拟值

System.out.println(app.say2()); //null,模拟默认值

final App appNew = newApp();

System.out.println(appNew.say());//Hello World,未被模拟,方法实际值

System.out.println(App.staticSay()); //Still hello world,未被模拟,方法实际值//验证

newVerifications() {

{//验证say模拟方法被调用

app.say();

times= 1;

}

{

appNew.say();

times= 1;

}

{//验证staticSay模拟方法被调用,且调用了1次

App.staticSay();

times= 1;

}

};

}

}

四、Expectations传参,局部模拟

/*** 测试类*/

public classAppTest002 {

@Testpublic voidtestSay() {final App app = newApp();//录制,带参数表示局部模拟【针对所有实例的局部模拟,具体到某个方法的模拟,其它方法不模拟】

new Expectations(App.class) {{

app.say();

result= "say";

}};//回放

System.out.println(app.say()); //say,模拟值

System.out.println(app.say2()); //Hello World 2 ,未被模拟,方法实际值

System.out.println(new App().say()); //say,模拟值

System.out.println(App.staticSay()); //Still hello world,未被模拟,方法实际值

}

}

五、MockUp局部模拟,可重写原有方法的逻辑,比较灵活,推荐使用

/*** 测试类*/

public classAppTest003 {

@Testpublic voidtestSay() {//局部模拟【针对所有实例的局部模拟,具体到某个方法的模拟,其它方法不模拟】

new MockUp(App.class){

@Mock

String say(){return "say";

}

};//回放

System.out.println(new App().say()); //say,模拟值

System.out.println(new App().say2()); //Hello World 2,未被模拟,方法实际值

System.out.println(App.staticSay()); //Still hello world,未被模拟,方法实际值

}

}

六、MockUp如何模拟私有方法、静态方法、静态块、构造函数等

1.模拟私有属性(实例属性和类属性),MockUp不支持,采用如下方式

//模拟实例的字段

Deencapsulation.setField(Object objectWithField, String fieldName, Object fieldValue)//模拟类的静态字段

Deencapsulation.setField(Class> classWithStaticField, String fieldName, Object fieldValue)

2.模拟私有方法,MockUp不支持,采用如下方式

//模拟实例方法,注意参数不能为null,如果要传null请使用带参数类型的另一个重载方法

Deencapsulation.invoke(Object objectWithMethod, String methodName, Object... nonNullArgs)//模拟类方法

Deencapsulation.invoke(Class> classWithStaticMethod, String methodName, Object... nonNullArgs)

3.模拟静态方法

和模拟实例方法一样,去掉static即可

4.模拟静态块

//mock静态代码块

@Mockvoid$clinit(Invocation invocation){

}

5.模拟实例块和构造函数

//mock代码块和构造函数

@Mockvoid$init(Invocation invocation) {

}

6.模拟接口,MockUp不支持,采用@Capturing

/*** 被模拟的接口*/

public interfaceIUserService {

String getUserName( );

}

public class UserServiceImpl implementsIUserService {

@OverridepublicString getUserName() {return "Bob";

}

}

/*** 接口模拟测试*/

public classIUserServiceTest {/*** MockUp不能mock接口方法,可以用来生成接口实例*/@Testpublic voidgetUserNameTest001(){

MockUp mockUp = new MockUp(){

@Mock

String getUserName( ){return "Jack";

}

};

IUserService obj= newUserServiceImpl();

System.out.println(obj.getUserName());//Bob,mock失败

obj=mockUp.getMockInstance();

System.out.println(obj.getUserName());//Jack,mockUp生成的实例,和自己写一个接口实现一样

obj= newUserServiceImpl();

System.out.println(obj.getUserName());//Bob,mock失败

}/*** @Capturing 注解可以实现mock接口,所有实现类的实例均被mock

*@parambase*/@Testpublic void getUserNameTest002(@Capturing finalIUserService base){

IUserService obj= newUserServiceImpl();

System.out.println(obj.getUserName());//mock成功,返回模拟默认值null//录制

newExpectations(){

{

base.getUserName();

result= "Jack";

}

};

System.out.println(obj.getUserName());//Jack

obj= newIUserService() {

@OverridepublicString getUserName() {return "Alice";

}

};

System.out.println(obj.getUserName());//Jack

}

}

七、MockUp模拟方法中调用原方法

/*** 模拟方法调用原方法逻辑测试*/

public classJSONObjectTest {

@Testpublic voidgetTest(){

JSONObject jsonObject= newJSONObject();

jsonObject.put("a","A");

jsonObject.put("b","B");

jsonObject.put("c","C");

System.out.println(jsonObject.get("a")); //A

System.out.println(jsonObject.get("b")); //B

System.out.println(jsonObject.get("c")); //C

new MockUp(){

@Mock

Object get(Invocation invocation,Object key){if("a".equals(key)){return "aa";

}else{//调用原逻辑

returninvocation.proceed(key);

}

}

};

System.out.println(jsonObject.get("a")); //aa

System.out.println(jsonObject.get("b")); //B

System.out.println(jsonObject.get("c")); //C

}

}

八、MockUp单元测试用例单个跑正常,批量跑失败可能的原因

1.测试方法使用了共享变量,相互影响。

2.在一个测试方法里多次MockUp同一个类,将某个类需要mock的方法均写在一个new MockUp里即可解决,原因未知。

3.在测试方法里的MockUp,在方法结束前,调用一下mockUp.tearDown。

jmockit教程_jmockit使用总结-MockUp重点介绍相关推荐

  1. jmockit教程_JMockit常用操作

    JMockit常用操作 目录 1 基本概念 1.1 常用注解 @Mocked:被修饰的对象将会被Mock,对应的类和实例都会受影响(同一个测试用例中) @Injectable:仅Mock被修饰的对象 ...

  2. jmockit教程_Jmockit(一): 入门

    1 pom配置 testng + jmockit,使用junit也可以 org.testng testng 6.14.3 test org.jmockit jmockit 1.41 test 2 程序 ...

  3. jmockit教程_Jmockit教程(各种整理的心得)

    Paste_Image.png 在JMockit库, Expectations(期望)API提供了使用自动化的开发人员测试mock的丰富的支持. 当mock使用,在测试的重点是代码的被测行为,如通过其 ...

  4. jmockit教程_jmockit demo

    1.@Mocked,标识一个指定的class的实例或被测对象的参数被Mock掉. 2.@Capturing,标识一个被Mock的对象,从该对象派生的子类也被Mock了. 3.@Injectable,标 ...

  5. Midjourney|文心一格prompt教程[基础篇]:注册使用教程、风格设置、参数介绍、隐私模式等

    Midjourney|文心一格prompt教程[基础篇]:注册使用教程.风格设置.参数介绍.隐私模式等 开头讲一下为什么选择Midjourney和文心一格,首先Midjourney功能效果好不多阐述: ...

  6. 会议重点介绍芯片设计中的人工智能

    会议重点介绍芯片设计中的人工智能 Conference highlights AI in chip design, IoT 旧金山-谷歌正在试验机器学习(ML)来执行IC设计中的地点和路线,并取得了很 ...

  7. 【建站系列教程】3.1、cookie介绍

    [建站系列教程]3.1.cookie介绍 cookie的应用场景 1 小说网站的字体.颜色.背景颜色设置 2 隐藏url里面的参数 cookie的通俗介绍 cookie的基本用法 js版本 jQuer ...

  8. Arduino可穿戴开发入门教程LilyPad和LilyPad Simple的介绍

    Arduino可穿戴开发入门教程LilyPad和LilyPad Simple的介绍 LilyPad和LilyPad Simple的介绍 LilyPad和LilyPad Simple是LilyPad微控 ...

  9. Quartz教程三:Job与JobDetail介绍

    Quartz教程三:Job与JobDetail介绍 原文链接 | 译文链接 | 翻译:nkcoder | 校对: 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感 ...

最新文章

  1. 《编写高质量代码:改善c程序代码的125个建议》——建议3-5:避免使用浮点数作为循环计数器...
  2. 关于adb devices连不上手机的几种情况
  3. [development][PCRE] old PCRE
  4. 提高阅读源代码的效率 转
  5. 使用 HTTP 缓存防止不必要的网络请求
  6. effective C++ 条款 3:尽可能使用const
  7. Teams团队的成员列表API的已知问题
  8. 日常spoken英语学习
  9. can't request region for resource [mem 0xfed40080-0xfed40fff]问题的解决办法
  10. input readonly 光标显示问题
  11. Firefox下强制页面缓存失效的设置方法
  12. crfpp python
  13. Redis教程:数据对象分析(二)
  14. 网站SEO优化--Flash站优化方法
  15. php爬取网站所有链接,php 爬取超链接
  16. 【SVPWM】SVPWM算法推导及其Simulink仿真(二)
  17. win8.1虚拟机装linux,Linux VirtualBox安装Win8.1报错0x000000C4怎么办?
  18. 【Testin实验室】MoiMark安卓中国终端体验性能排行榜(11月报)
  19. Unity 最新UnityWebRequest下载,同时显示下载进度,和 显示网速,今天贴出来和大家分享
  20. 模拟信号隔离器|隔离放大器|隔离变送器 常见问题解答

热门文章

  1. sklearn学习笔记5:朴素贝叶斯
  2. 身边的套套故事:有些人非得真在行
  3. 线段树(区间修改 + 根节点查询):Just a Hook
  4. 全基因组关联分析(GWAS)软件:emmax
  5. 信道估计功率归一化设定原则
  6. 外汇报价接口支持常用汇率查询
  7. OpenStack,开源云十年
  8. BCH应用热潮助力BCH生态壮大
  9. 让珍贵的非物质文化遗产“活”起来----青城派 刘绥滨掌门人
  10. exfat linux 编译,嵌入式 linux 基于fuse 的 exfat 文件系统实现