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手法完一不同,但有异曲同工之妙。