2015-01-15 121 views
3

我需要編寫一個模擬java.lang.Class類的實例的測試。 這是可能通過PowerMock?我們可以使用PowerMock創建一個java.lang.Class的模擬實例嗎?

我試圖做到以下幾點:

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)。順便說一句,有[鏈接](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()來,我想到的東西,我不能提供類的模擬一個實例,我真的很期待,因爲我沒有classpath中它(它是更高層的一部分)。 我會在確切的場景中添加一些說明問題。 – 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''是你的條件之一) – nrainer

+0

因爲被測試的類是應用程序服務器中較低層的一部分,並且它看到「someObject」(來自示例)作爲特定的接口。在運行時,我需要將其更改爲具有特定行爲,當「someObject」是特定實現的實例時,它是上層的一部分。當測試用例被執行時,我只能訪問下層。 – vap78

相關問題