我们可以使用 PowerMock 创建一个 java.lang.Class 的模拟实例吗?

Can we create a mocked instance of java.lang.Class with PowerMock?

我需要编写一个模拟 java.lang.Class class 实例的测试。 这可以通过 PowerMock 实现吗?

我尝试执行以下操作:

PowerMock.createMock(Class.class);

结果是:

java.lang.IllegalAccessError: java.lang.Class
    at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:40)
    at org.powermock.reflect.internal.WhiteboxImpl.newInstance(WhiteboxImpl.java:223)
    at org.powermock.reflect.Whitebox.newInstance(Whitebox.java:139)
    at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2146)
    at org.powermock.api.easymock.PowerMock.createMock(PowerMock.java:89)

根据 PowerMock 的文档,这应该是可能的,但我仍然收到此错误。

有人成功做到了吗?

编辑: 为什么我需要这个? 在经过测试的编码中有以下语句:

if (someObject.getClass().getName().equals(SOME_CLASS_NAME_THAT_I_DONT_HAVE_ACCESS_TO)) { ... do some stuff ... }

我需要测试才能到达 "if" 中的编码,但我什至无法提供具有相应名称的 class 的模拟实例。

作为解决方法,我可以在测试中创建一个具有相同名称和包的 class,但它很难看。

编辑 2:

我也尝试了 this link

的建议
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.junit.Test;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Test1.class})
public class Test1 {

    @Test
    public void test() {
        PowerMock.createMock(Class.class);
    }

}

结果是一样的:"java.lang.IllegalAccessError: java.lang.Class"

所以作为最终结果 - 似乎没有办法创建 java.lang.Class

的模拟实例

谢谢

您确定需要模拟 class 对象吗? 是否有特定原因导致您不能只执行以下操作?

public class MyTest {
   public static class TestClass {
       public void doFoo() {}
   }

   @Test
   public void myTest() {
       doStuff(TestClass.class);
   }
}

根据这个说法,

...

at java.lang.reflect.Constructor.newInstance(Constructor.java:526)

...

PowerMock(使用 Objenesis 库)尝试实例化 java.lang.Class,它只能由 JVM 实例化。来自 docs:

Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.

很快,我几乎可以肯定无法手动创建 java.lang.Class 的实例。如有错误请指正

顺便说一句,

Unfortunately I need to change the return value of the getClass().getName()

mocking getClass() 方法不适合你吗?

您可以使用 JavaCompiler 即时编译源文件,并使用 URLClassLoader 加载 class 实例。

例如:How do I programmatically compile and instantiate a Java class?

为什么不在运行时加载class

Class<?> cls = Class.forName("org.package.Class");
Class<? extends Collection> clazz = Collection.class;
Constructor c = PowerMockito.mock(Constructor.class);
Collection collection = mock(Collection.class);
    
PowerMockito.mockStatic(clazz);
when(clazz.getDeclaredConstructor(int.class)).thenThrow(NoSuchMethodException.class);
when(clazz.getDeclaredConstructor()).thenReturn(c);
when(c.newInstance()).thenReturn(collection);

verify(clazz).getDeclaredConstructor(int.class);
verify(clazz).getDeclaredConstructor();