jmockit更好用的mock工具

jmockit更好用的mock工具


后端

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

脚本录制规范

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

mock整个类

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

示例:

//Expectations对外部类的mock对象进行录制
public class ExpectationsTest {
@Mocked
Calendar cal;
@Test
public void testRecordOutside() {
new Expectations() {
{
// 对cal.get方法进行录制,并匹配参数 Calendar.YEAR
cal.get(Calendar.YEAR);
result = 2016;// 年份不再返回当前小时。而是返回2016年
// 对cal.get方法进行录制,并匹配参数 Calendar.HOUR_OF_DAY
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时不再返回当前小时。而是返回早上7点钟
}
};
Assert.assertTrue(cal.get(Calendar.YEAR) == 2016);
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
// 因为没有录制过,所以这里月份返回默认值 0
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == 0);
}
}

对类部分mock

//通过Expectations对其构造函数mock对象进行录制
public class ExpectationsConstructorTest2 {
// 把类传入Expectations的构造函数
@Test
public void testRecordConstrutctor1() {
Calendar cal = Calendar.getInstance();
// 把待Mock的类传入Expectations的构造函数,可以达到只mock类的部分行为的目的
new Expectations(Calendar.class) {
{
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时永远返回早上7点钟
}
};
Calendar now = Calendar.getInstance();
// 因为下面的调用mock过了,小时永远返回7点钟了
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == 7);
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
}
// 把对象传入Expectations的构造函数
@Test
public void testRecordConstrutctor2() {
Calendar cal = Calendar.getInstance();
// 把待Mock的对象传入Expectations的构造函数,可以达到只mock类的部分行为的目的,但只对这个对象影响
new Expectations(cal) {
{
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时永远返回早上7点钟
}
};
// 因为下面的调用mock过了,小时永远返回7点钟了
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
// now是另一个对象,上面录制只对cal对象的影响,所以now的方法行为没有任何变化
Calendar now = Calendar.getInstance();
// 不受mock影响
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == (new Date()).getHours());
// 不受mock影响
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
}
}

验证

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