现在的 JMockit 已经偷偷升级到了 1.23 版了,在 JVM 上的 Mock 工具中就数它最无敌了,因为它抢夺了最佳控制点 --javaagent,可以说它是无所不能的。一般我们使用 JMockit 是通过两种方式,new MockUp
和 new Expectations
. JMock 不仅能够 Mock 类的所有方法,还能部分 Mock -- 这个是 new Expectations
的默认行为。所以这里我们来看下在使用 new Expectations
的情况下如何对类的部份静态方法或部分实例方法进行 Mock。
大致表述一下,共分为三种情况
- 针对类进行 Mock, 只有录制的静态方法被 Mock 住,其他的静态方法或实例方法都会调用实际实现
- 针对某一实例进行 Mock,只在调用该实例已录制的方法才被 Mock 住,静态方法或新建实例调用任何方法都是实际实现
- 针对类进行 Mock,但录制的是一个实例方法,那么该实例或任何新建实例在调用该录制方法时都会被 Mock 住
不知道上面在说什么,本来就是空洞无凭,所以还是下实例,假定要测试下面这个类,或者说是测试使用到下面类的其他类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class ClassToBeMocked { public static String f1(){ return "f1"; } public static String f2() { return "f2"; } public String f3() { return "f3"; } public String f4() { return "f4"; } } |
然后分三个测试用例来各自说明
一: 针对类,Mock 了一个静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Test public void testPartialMockingStaticMethods() { new Expectations(ClassToBeMocked.class) {{ ClassToBeMocked.f1(); //只有该静态 f1() 方法受影响 result = "mocked"; }}; //mocked assertEquals("mocked", ClassToBeMocked.f1()); assertEquals("f2", ClassToBeMocked.f2()); assertEquals("f3", new ClassToBeMocked().f3()); } |
Mock 了一个静态方法 f1(), 只有调用该方法时才使用 Mock 的结果,其他的静态或实例方法都不受影响,会调用实际的实现。
二:针对某一实例,Mock 了一个实例方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Test public void testPartialMockingInstanceMethods() { final ClassToBeMocked mockedInstance = new ClassToBeMocked(); new Expectations(mockedInstance) {{ mockedInstance.f3(); //只有该实例的 f3() 方法受影响 result = "mocked"; }}; //mocked assertEquals("mocked", mockedInstance.f3()); assertEquals("f3", new ClassToBeMocked().f3()); assertEquals("f1", ClassToBeMocked.f1()); assertEquals("f4", mockedInstance.f4()); } |
只有调用该实例的 f3() 方法才使用 Mock 的结果,其他不管是调用别的实例的 f3() 还是别的方法,或任何静态方法都不受影响。
三:针对类,Mock 了一个具体实例的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Test public void testPartialMockingInstanceMethodsWithClass() { ClassToBeMocked anotherInstance = new ClassToBeMocked(); final ClassToBeMocked mockedInstance = new ClassToBeMocked(); new Expectations(ClassToBeMocked.class) {{ mockedInstance.f3(); //任何 ClassToBeMocked 实例都受到影响,也包括上面的 anotherInstance result = "mocked"; }}; //mocked assertEquals("mocked", mockedInstance.f3()); assertEquals("mocked", anotherInstance.f3()); assertEquals("mocked", new ClassToBeMocked().f3()); assertEquals("f1", ClassToBeMocked.f1()); assertEquals("f4", mockedInstance.f4()); } |
new Expectations(ClassToBeMocked.class) 是一个类,但 Mock 是一个具体实例的 f3() 方法,结果是任何访类的实例(无论何时创建的) 方法 f3() 都被 Mock 住。其他的实例或静态方法不受影响。官方的解释是如果是一个类出现在 Expectations 的参数中,就相当于该类的构造方法被 Mock 住,由此生成的实例的被录制方法都将被波及。
至于属性的 Mock, 它与方法的 Mock 是一致的,原本在 Scala 中方法和属性就不再分得那么清楚。
参考: 1. Partial Mocking
本文链接 https://yanbin.blog/jmockit-partial-mock/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。