同Exepectations一样,MockUp的使用频率也十分高。 我们可以借鉴分析Exepectations录制原理一样,分析MockUp是如何Mock的。
以类的Mock中提到的测试程序ClassMockingByMockUpTest为例,我们看看MockUp对AnOrdinaryClass类重定义后是什么样子呢?通过一些反编译工具,我们抓取到的反编译代码如下:
public class AnOrdinaryClass { public AnOrdinaryClass() { TestRun.lineExecuted(0, 4); super(); } public static int staticMethod() { if (mockit.internal.state.TestRun.updateFakeState("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", -1)) { return AnOrdinaryClassMockUp.staticMethod(); } else { TestRun.lineExecuted(0, 7); return 1; } } public int ordinaryMethod() { if (mockit.internal.state.TestRun.updateFakeState("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", -1)) { return ((AnOrdinaryClassMockUp)mockit.internal.state.TestRun.getFake("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp")).ordinaryMethod(); } else { TestRun.lineExecuted(0, 12); return 2; } } public final int finalMethod() { if (mockit.internal.state.TestRun.updateFakeState("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", -1)) { return ((AnOrdinaryClassMockUp)mockit.internal.state.TestRun.getFake("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp")).finalMethod(); } else { TestRun.lineExecuted(0, 17); return 3; } } public int navtiveMethod() { mockit.internal.state.TestRun.updateFakeState("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", -1); return ((AnOrdinaryClassMockUp)mockit.internal.state.TestRun.getFake("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp")).navtiveMethod(); } private int privateMethod() { if (mockit.internal.state.TestRun.updateFakeState("cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", -1)) { return (Integer)NegativeArraySizeException.$FMB.invoke(this, (Method)null, new Object[]{"cn/jmockit/demos/usual/ClassMockingByMockUpTest$AnOrdinaryClassMockUp", "cn/jmockit/demos/AnOrdinaryClass", 2, "privateMethod", "()I", -1}); } else { TestRun.lineExecuted(0, 25); return 5; } } public int callPrivateMethod() { TestRun.lineExecuted(0, 30); return this.privateMethod(); } }
通过上面的代码,我们可以看到,JMockit在AnOrdinaryClass的每个方法(只要是经@Mock修饰过的)中插入了一个分支,这个分支就是走MockUp类(即new MockUp{{}}匿名类或extends MockUp的子类)的mock方法,因此就达到了Mock的目的。 这与Exepectations的Mock手法完一不同,但有异曲同工之妙。