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

空扰寡人 提交于 2021-02-20 13:53:26

问题


I need to write a test that mocks a instance of the java.lang.Class class. Is this possible via PowerMock?

I tried to do following:

PowerMock.createMock(Class.class);

And the result is:

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)

According to the documentation of PowerMock this should be possible but still I get this error.

Did someone manage to do this?

Edit: Why do I need this? In the tested coding there is following statement:

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

I need my test to reach the coding inside the "if" and I CANNOT provide even a mocked instance of the class that has the corresponding name.

As a workaround I can just create a class with the same name and package in the tests but it is ugly.

Edit2:

I tried also the suggestions from 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);
    }

}

And the result is the same: "java.lang.IllegalAccessError: java.lang.Class"

So as a final result - it seems that there is no way to create a mocked instance of java.lang.Class

Thank you


回答1:


According to this statement,

...

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

...

PowerMock (using Objenesis library) tries to instantiate java.lang.Class, which could be instantiated only by JVM. From 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.

Shortly, I'm almost sure that it's not possible to make instance of java.lang.Class manually. Please correct me if I wrong.

By the way,

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

Isn't mocking of getClass() method an option for you?




回答2:


You could use the JavaCompiler to compile a source file on the fly and a URLClassLoader to load the class instance.

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




回答3:


Why don't you load the class at runtime?

Class<?> cls = Class.forName("org.package.Class");



回答4:


Are you sure you need to mock the class object? Is there a specific reason why you can't just do the following?

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

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


来源:https://stackoverflow.com/questions/27964561/can-we-create-a-mocked-instance-of-java-lang-class-with-powermock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!