Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 319
vap78 Avatar asked Jan 15 '15 13:01

vap78


People also ask

How do you mock a class in PowerMock?

Use PowerMockito. mockStatic() to a mock a static class or all the static methods in a class. Use PowerMockito. spy() to mock a specific static method.

Is PowerMock a mocking framework?

PowerMock is a framework that extends other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.

Can Mockito and PowerMock be used together?

Mockito allows us to create mock objects. Since static method belongs to the class, there is no way in Mockito to mock static methods. However, we can use PowerMock along with Mockito framework to mock static methods.

How do you mock a private class with PowerMock?

Powermock – A Brief Introduction For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.


2 Answers

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?

like image 168
bsiamionau Avatar answered Oct 27 '22 20:10

bsiamionau


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?

like image 44
lance-java Avatar answered Oct 27 '22 20:10

lance-java