静态导入静态嵌套类失败,如何跨包测试不可修改的com.foo包内私有方法
问题根因
- 静态嵌套类
B没有添加public修饰符,属于包级私有访问权限,仅允许com.foo包内的类直接访问,跨包场景下静态导入也无法识别该类 functionA()是类A的private私有方法,常规语法下仅允许类A内部的代码调用functionB()是类B的实例方法,不是静态方法,不能直接通过类名B.functionB()调用,必须先实例化B对象再调用
可行方案
两种方案都无需修改com.foo包下的任何代码,符合约束要求:
方案1:纯JDK反射实现(无第三方依赖)
通过Java反射机制禁用访问权限检查,直接调用私有/包级私有成员,示例代码如下:
package com.foo.test; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception { // 1. 加载包级私有静态类A$B Class<?> bClazz = Class.forName("com.foo.A$B"); // 2. 实例化B类对象 Object bInstance = bClazz.getDeclaredConstructor().newInstance(); // 3. 创建A的匿名子类实例(A为抽象类,无法直接实例化,若A包含抽象方法需在此实现) A aInstance = new A() {}; // 4. 给B类的a字段赋值 Field aField = bClazz.getDeclaredField("a"); aField.setAccessible(true); aField.set(bInstance, aInstance); // 可选1:调用B的functionB,间接触发functionA执行 Method functionB = bClazz.getDeclaredMethod("functionB"); functionB.setAccessible(true); functionB.invoke(bInstance); // 可选2:直接反射调用A的私有方法functionA Method functionA = A.class.getDeclaredMethod("functionA"); functionA.setAccessible(true); functionA.invoke(aInstance); } }
方案2:PowerMock单元测试框架实现
如果是做单元测试,可使用PowerMock框架简化私有方法调用逻辑,示例基于JUnit4:
package com.foo.test; import com.foo.A; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.lang.reflect.Method; @RunWith(PowerMockRunner.class) @PrepareForTest(A.class) public class AFunctionTest { @Test public void testFunctionA() throws Exception { // 创建A的匿名子类实例 A aInstance = new A() {}; // 获取并调用私有方法 Method functionA = A.class.getDeclaredMethod("functionA"); functionA.setAccessible(true); functionA.invoke(aInstance); } }
内容的提问来源于stack exchange,提问作者Megha Sharma
相关产品推荐
相关产品推荐

