2015-01-15 2 views
3

Мне нужно написать тест, издевающийся над экземпляром класса java.lang.Class. Возможно ли это через PowerMock?Можем ли мы создать насмешливый экземпляр java.lang.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 ... } 

мне нужна мой тест, чтобы достичь кодирования внутри «если» и я не могу представить даже высмеивали экземпляр класса, который имеет соответствующее название.

В качестве обходного решения я могу просто создать класс с таким же именем и пакетом в тестах, но он уродлив.

Edit2:

Я попытался также предложения от 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

Спасибо

ответ

2

Согласно этому утверждению,

...

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()

Не насмешливый из getClass() метода вариант для вас?

+0

Ну, я могу издеваться над методом getClass(), но ему нужно вернуть экземпляр класса java.lang.Class :) И так как я не могу вернуть насмешливый экземпляр, я не могу еще глумиться с методом getName(). Единственное, что я могу сделать, это просто создать реальный класс с тем же именем и пакетом и вернуть его там - я упомянул об этом как обходном пути. – vap78

+0

@ vap78, я нашел подтверждение моего предположения, [см. Вопрос 3.1] (https://code.google.com/p/powermock/wiki/FAQ). btw, есть [link] (https://code.google.com/p/powermock/source/browse/trunk/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/ system/SystemClassUserTest.java) к обходу. они предлагают использовать аннотацию [PrepareForTest] (http://powermock.googlecode.com/svn/docs/powermock-1.3.5/apidocs/org/powermock/core/classloader/annotations/PrepareForTest.html). – bsiamionau

+0

@ vap78, сообщите нам, если это помогает – bsiamionau

-1

Вы уверены, что вам нужно высмеять объект класса? Есть ли конкретная причина, по которой вы не можете просто сделать следующее?

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

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

К сожалению, мне нужно, чтобы изменить возвращаемое значение GetClass(). GetName() к чему-то, что я ожидал и я не могу предоставить макет экземпляр класса, который я действительно ожидал, потому что я не имею путь к классам он (это часть более высокого уровня). Я уточню вопрос с точным сценарием. – vap78

1

Вы можете использовать JavaCompiler для компиляции исходного файла на лету и URLClassLoader для загрузки экземпляра класса.

Например: How do I programmatically compile and instantiate a Java class?

+0

Хорошая идея, но в целом у меня есть более простое решение - просто создайте настоящий класс с тем же пакетом и именем. Ваше предложение будет полезно, если создание такого класса невозможно, из-за некоторых других условий (например, вызвать другие проблемы во время выполнения и т. Д.). – vap78

0

Почему вы не загрузить класс во время выполнения?

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

Нет. У меня нет доступа к этому классу при запуске модульных тестов. – vap78

+0

Почему? Вы можете получить доступ к классу через '' someObject.getClass(). GetClassLoader(). LoadClass ("org.package.Class") ''? ('' someObject' является одним из ваших условий if) – nrainer

+0

Поскольку тестируемый класс является частью более низкого уровня на сервере приложений и он видит «someObject» (из примера) в качестве определенного интерфейса. Во время выполнения мне нужно было изменить его, чтобы иметь определенное поведение, когда «someObject» является экземпляром конкретной реализации, которая является частью верхнего уровня. Когда тестовый пример выполняется, я имею доступ только к нижнему уровню. – vap78

Смежные вопросы