健兼
jmockit更好用的mock工具
jianzhang

之前试过powermock,虽然可以mock 静态方法,但是得依赖maven 插件,而后找到了jmockit,配置非常简洁、性能高。 中文文档

脚本录制规范

1
new Expectations() {
2
// 这是一个Expectations匿名内部类
3
{
4
// 这是这个内部类的初始化代码块,我们在这里写录制脚本,脚本的格式要遵循下面的约定
5
//方法调用(可是类的静态方法调用,也可以是对象的非静态方法调用)
6
//result赋值要紧跟在方法调用后面
7
//...其它准备录制脚本的代码
8
//方法调用
9
//result赋值
10
}
11
};
12
13
// 还可以再写new一个Expectations,只要出现在重放阶段之前均有效。
14
new Expectations() {
15
16
{
17
//...录制脚本
18
}
19
};

mock整个类

@Injectabe: 只mockjmockit初始化的实例; @Mocked: mock标注类的所有实例,包括手动实例化; @Capturing: 影响接口所有子类的实现,包括动态代理;

示例:

1
//Expectations对外部类的mock对象进行录制
2
public class ExpectationsTest {
3
@Mocked
4
Calendar cal;
5
6
@Test
7
public void testRecordOutside() {
8
new Expectations() {
9
{
10
// 对cal.get方法进行录制,并匹配参数 Calendar.YEAR
11
cal.get(Calendar.YEAR);
12
result = 2016;// 年份不再返回当前小时。而是返回2016年
13
// 对cal.get方法进行录制,并匹配参数 Calendar.HOUR_OF_DAY
14
cal.get(Calendar.HOUR_OF_DAY);
15
result = 7;// 小时不再返回当前小时。而是返回早上7点钟
16
}
17
};
18
Assert.assertTrue(cal.get(Calendar.YEAR) == 2016);
19
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
20
// 因为没有录制过,所以这里月份返回默认值 0
21
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == 0);
22
}
23
24
}

对类部分mock

1
//通过Expectations对其构造函数mock对象进行录制
2
public class ExpectationsConstructorTest2 {
3
4
// 把类传入Expectations的构造函数
5
@Test
6
public void testRecordConstrutctor1() {
7
Calendar cal = Calendar.getInstance();
8
// 把待Mock的类传入Expectations的构造函数,可以达到只mock类的部分行为的目的
9
new Expectations(Calendar.class) {
10
{
11
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
12
cal.get(Calendar.HOUR_OF_DAY);
13
result = 7;// 小时永远返回早上7点钟
14
}
15
};
16
Calendar now = Calendar.getInstance();
17
// 因为下面的调用mock过了,小时永远返回7点钟了
18
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == 7);
19
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
20
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
21
}
22
23
// 把对象传入Expectations的构造函数
24
@Test
25
public void testRecordConstrutctor2() {
26
Calendar cal = Calendar.getInstance();
27
// 把待Mock的对象传入Expectations的构造函数,可以达到只mock类的部分行为的目的,但只对这个对象影响
28
new Expectations(cal) {
29
{
30
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
31
cal.get(Calendar.HOUR_OF_DAY);
32
result = 7;// 小时永远返回早上7点钟
33
}
34
};
35
36
// 因为下面的调用mock过了,小时永远返回7点钟了
37
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
38
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
39
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
40
41
// now是另一个对象,上面录制只对cal对象的影响,所以now的方法行为没有任何变化
42
Calendar now = Calendar.getInstance();
43
// 不受mock影响
44
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == (new Date()).getHours());
45
// 不受mock影响
46
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
47
}
48
}

验证

1
new Verifications() {
2
// 这是一个Verifications匿名内部类
3
{
4
// 这是这个内部类的初始化代码块,我们在这里写验证脚本,脚本的格式要遵循下面的约定
5
//方法调用(可是类的静态方法调用,也可以是对象的非静态方法调用)
6
//times/minTimes/maxTime 表示调用次数的限定要求。赋值要紧跟在方法调用后面,也可以不写(表示只要调用过就行,不限次数)
7
//...其它准备验证脚本的代码
8
//方法调用
9
//times/minTimes/maxTime赋值
10
}
11
};
12
13
还可以再写new一个Verifications,只要出现在重放阶段之后均有效。
14
new Verifications() {
15
16
{
17
//...录制脚本
18
}
19
};
目录