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() {
{ //...录制脚本 }};