JMockit学习笔记
一、在eclipse下建立JMockit工程
1、下载最新版JMockit(jmockit-1.4.zip);
2、解压后的文件夹包含有:library jars, source files, samples, API javadocs, and additional documentation;
3、将jmockit.jar添加到项目classpath中;
特别的:
1)确保classpath中Jar包的顺序:jmockit的jar包必须在junit之前(通过Order and Export" 标签上下移动);
2)eclipse项目所用JRE来自于JDK,而不是“简洁”版的JRE,因为后者缺少本地类库“attach”。

二、行为和状态的测试
基于行为(Behavior-based)的mock是站在目标测试代码外面的角度的,通常主要模拟行为,而基于状态
(State-based)的是站在目标测试代码内部的。我们可以对传入的参数进行检查、匹配,才返回某些结果。
Mockup用于State-based测试。
二、声明和使用mock类型
1、字段,期望块的字段与期望块内的局部属性字段使用@Mocked来声明Mock类型。
2、参数,方法的参数声明来引入一个Mock类型。
第一种情况,属性字段是属于测试类或者一个mockit.Expectations子类(一个expectation期望块的内部的局部
属性字段)。
第二种情况,参数必须是属于某个测试方法(@Test标签下的方法)。
在所有的情况,一个mock属性字段或者参数声明,都可以通过使用@Mocked声明。对于方法mock的参数或者
在expectations期望块中定义的mock属性字段来说,该注解是可选的,而对于定义在测试类(XXXTest类)中的
属性字段,@Mocked标签是必须,这是为了防止和该测试类的其它不需要mock的字段属性产生冲突。
package main;
import static org.junit.Assert.*;
import java.io.Serializable;
import org.junit.Test;
import mockit.Expectations;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import mockit.Verifications;
/*
* 一个用户接口(外部依赖)
*/
interface Dependency {
String doSomething(boolean b);
}
// 声明变量类型MultiMock(它实现两个接口,作用域是整个测试类)
public class MultiMocksTest<MultiMock extends Dependency & Runnable> {
@Mocked
MultiMock multiMock;
@Test
public void mockFieldWithTwoInterfaces() {
new NonStrictExpectations() {
{
multiMock.doSomething(false);
result = "test";
}
};
multiMock.run();
assertEquals("test", multiMock.doSomething(false));
// 验证run()方法执行一次
new Verifications() {
{
multiMock.run();
}
};
}
@Test
// 声明变量类型M,它实现两个接口,作用域为该测试方法
// final M mock 前的@Mocked注解是可选的
public <M extends Dependency & Serializable> void mockParameterWithTwoInterfaces(
@Mocked final M mock) {
new Expectations() {
{
mock.doSomething(true);
result = "";
}
};
assertEquals("", multiMock.doSomething(true));
}
}
3、对于一个返回值不为void类型的方法,Expectations中如何模拟方法返回值:
1)其返回值可以通过Expectations的result属性域来记录
2)Expectations的returns(Object)方法来记录
例如,方法返回一个Throwable异常类,只需将一个类型实验赋给result(注意,异常类只能通过result方式
赋值)。
package main;
import mockit.Expectations;
import org.junit.Test;
public class UnitUnderTest {
// 1、构造方法
private OutWork work = new OutWork();
public void doSomthing() {
// 2、intReturningMethod()方法
int n = work.intReturningMethod();
for (int i = 0; i < n; i++) {
String s;
try {
// 3、stringReturningMethod()方法
s = work.stringReturningMethod();
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
}
// 其它逻辑...
}
@Test
public void test() {
new Expectations() {
OutWork work;
{
// 1、构造方法模拟
new OutWork();
// 2、intReturningMethod()方法模拟
work.intReturningMethod();
result = 3;
// 3、stringReturningMethod()方法模拟
work.stringReturningMethod();
// 方法分别返回三个值,两个字符串,一个异常
returns("str1", "str2");
result = new Exception("testException");
}
};
new UnitUnderTest().doSomthing();
}
}
class OutWork {
public int intReturningMethod() {
return 0;
}
public String stringReturningMethod() {
return "";
}
}
三、从严格到非严格
1、@Mocked+Expections块:会进行隐式校验(执行顺序和次数)
2、@Mocked+NonStrictExpections块:NonStrictExpections块中的Incovation可以非严格执行(不执行或者
执行N次,除非显示地指定执行次数)。
package main;
/*
* 用于Mock的接口
*/
public interface WinportUrlService {
public boolean hasWinport(String id);
public String getMsg();
public Throwable getWinportUrlThrowException(String id);
}
package main;
import static org.junit.Assert.*;
import mockit.Expectations;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import org.junit.Test;
public class IntroductionTest {
// @Mocked注解+Expectations/NonStrictExpectations块
@Mocked
private WinportUrlService winportUrlService = null;
@Test
public void testNoExceptions() {
final String memberId = "test";
// 未指定期望块,方法返回默认值
assertEquals(false, winportUrlService.hasWinport(memberId));
assertEquals(null, winportUrlService.getMsg());
assertEquals(null, winportUrlService.getWinportUrlThrowException(memberId));
}
@Test
public void testWithExpectations() {
final String memerId = "test";
// 步骤一:record
// 严格期望块
new Expectations() {
{
// 下面的Invocation必须严格执行
winportUrlService.hasWinport(memerId);
result = false;// 也可以是returns(false)
// 未指定执行次数
}
};
// 非严格期望块
new NonStrictExpectations() {
{
// 下面的Invocation非严格执行
winportUrlService.getMsg();
result = "test";// 也可以是returns("test")
// 未指定执行次数
}
};
// 步骤二:replay阶段
// hasWinport必须严格执行一次
assertEquals(false, winportUrlService.hasWinport(memerId));
// getMsg可以不执行或执行多次
assertEquals("test", winportUrlService.getMsg());
assertEquals("test", winportUrlService.getMsg());
// 下面的Invocation失败
// winportUrlService.getWinportUrlThrowException(memerId);
}
}
3、@NonStrict:可以在replay中调用或不调用。@NonStrict可以避免需要记录调用构造函数,或任何不感兴
趣的方法。
注意:@NonStrict它是针对类的属性非严格,类的属性适用于类中的所有测试方法。这个非严格的范围比
NonStrictExpections块的作用范围大很多,一旦使用了@NonStrict,Expections中的Incovation就变成了非严
格的invocation,因此其它测试方法还想在该属性的基础上使用Expections块是不可能的了。如果是这种情况
就需要这样使用(@Mocked+NonStrictExpectations块)。
package main;
import static org.junit.Assert.*;
import mockit.Expectations;
import mockit.NonStrict;
import org.junit.Test;
public class IntroductionTest2 {
// @NonStrict注解
@NonStrict
private WinportUrlService winportUrlService = null;
@Test
public void testWithExpectations() {
final String memberId = "test";
// 步骤一:record
// 用了@NonStrict,Expectation中的invocation就变成了非严格的invocation
new Expectations() {
{
// 下面的Invocation非严格执行
winportUrlService.hasWinport(memberId);
result = false;// 也可以是returns(false)
// 未指定执行次数
}
};
// 步骤二:replay阶段
// hasWinport可以不执行或执行多次
assertEquals(false, winportUrlService.hasWinport(memberId));
assertEquals(false, winportUrlService.hasWinport(memberId));
// 下面的Invocation成功
winportUrlService.getWinportUrlThrowException(memberId);
}
}
4、此外,若不指定执行次数,Expections块默认必须执行一次,NonStrictExpections块中的Invocation可执行
N次或不执行;若显式地指定执行次数(N次),二者的Invocation都必须执行N次
JMockit学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
随机推荐
- 2019面向对象程序设计(java)课程学习进度条
2019面向对象程序设计(java)课程学习进度条 周次 (阅读/编写)代码行数 发布博客量/评论他人博客数量 课余学习时间(小时) 学习收获最大的程序阅读或编程任务 1 20/10 1/0 5 九九 ...
- 28道java基础面试题-下
28道java基础面试题下 15.Java语言如何进行异常处理,关键字:throws.throw.try.catch.finally分别如何使用? 答:Java通过面向对象的方法进行异常处理,把各种不 ...
- MySQL学习笔记1——DDL
DDL 1.数据库 *查看所有数据库:SHOW DATABASES;*切换(选择要操作的)数据库:USE 数据库名;*创建数据库:CREATE DATABASES [IF NOT EXISTS] my ...
- URL、URI、URN之间的区别
URL统一资源定位符 URI统一资源标识符 URN统一资源名称 URL是URI的一个特例. URI由URL和URN两部分组成. 在java类中,URI类不包含任何访问资源的方法,它唯一的作用就是解析. ...
- Python中的赋值、深拷贝与浅拷贝(内存地址)
Python中的赋值.深拷贝与浅拷贝(内存地址) 1.python中的可变对象与不可变对象 (1) 可变对象:dict,list def dict_test(): a = {} b = a print ...
- 普通的行专列;oracle行专列;更新中。。。
题记 本来想写一个完整的表创建,但是其他人都写过啦,要不这样,你们有什么行转列的问题给我留言,我直接回答如何 Oracle的行转列 这篇文章不错:https://blog.csdn.net/huay_ ...
- 明解C语言 入门篇 第十二章答案
练习12-1 /* 用表示学生的结构体来显示高尾的信息 */ #include <stdio.h> #define NAME_LEN 64 /* 姓名的字符数 */ /*=== 表示学生的 ...
- Unsupervised Attention-guided Image-to-Image Translation
这是NeurIPS 2018一篇图像翻译的文章.目前的无监督图像到图像的翻译技术很难在不改变背景或场景中多个对象交互方式的情况下将注意力集中在改变的对象上去.这篇文章的解决思路是使用注意力导向来进行图 ...
- 解决Git 克隆代码 The remote end hung up unexpectedly错误
从GitHub上克隆一个项目一直不成功!猜想可能是文件太大超时或者网络太慢超时! 解决方案: 配置 git config -- git config -- 增加最低速时间,but,还是不行! 公司网络 ...
- 【UOJ#74】【UR #6】破解密码
[UOJ#74][UR #6]破解密码 题面 UOJ 题解 发现这个过程是一个字符串哈希的过程. 把第一位单独拿出来考虑,假设这个串是\(p+S\),旋转后变成了\(S+p\). 其哈希值分别是:\( ...