2012-05-09 8 views
3

我正在編寫Eclipse中的JUnit測試用於測試RCP-Eclipse-應用程序而沒有Maven。對於一些測試用例來說,用戶必須使用Powermock(使用Easymock)來模擬對象創建和靜態方法。Powermock導致Eclipse中的JUnit插件測試出現ClassNotFoundException,當從第三個引用(插件)

我有一個插件,其中包含將被測試的類以及包含相應測試的第二個插件。讓我們捐出他們PluginObject和PluginTest:

工作進展情況:

* PluginObject 
    - src 
     - ClassUnderTest 

* PluginTest 
- src 
    - TestCase 
- lib 
    - easymock 
    - powermock 
    - ... [aditional classes (like JavaAssist)] 

與在PLuginTest TestCase的的powermock-JAR的配置,並在插件艙單-Runtim配置運行正常,並返回所期望的結果。

我的TestCase下列行開始,目前使用@RunWith -Annotation:

@RunWith(PowerMockRunner.class) 
@PowerMockIgnore({ "javax.management.*", 
"javax.xml.parsers.*", 
"com.sun.org.apache.xerces.internal.jaxp.*", 
"javax.xml.*", 
"ch.qos.logback.classic.*", 
"org.slf4j.*", 
"org.eclipse.core.runtime.jobs.ISchedulingRule" }) 
@PrepareForTest ({Controller.class,ProcessLoaderFactory.class,Engine.class,CommandCollector.class}) 
@SuppressStaticInitializationFor({"Controller"," ProcessLoaderFactory","Engine","CommandCollector"}) 
public class ControllerTest { 
... 
[skipped package information due to copyrights] 

但我有想用Powermock在我的應用程序嘲諷多個插件,它似乎是一個好主意,對我來說,提取共享庫,另一個特殊的插件 - 姑且稱之爲Test.Util:

* PluginObject 
    - src 
     - ClassUnderTest 

* PluginTest 
- src 
    - TestCase 

* Test.Util 
- lib 
    - easymock 
    - powermock 
    - ... [aditional classes (like JavaAssist)] 

對於所有除了Powermock之外的其他庫我沒有問題,但是當我將Powermock從PluginTest移動到Test.Util-Plugin時,當初始化時,啓動JUnit PLugin-Test時,出現「ClassNotFoundException」。 (正常的JUnit測試不會拋出這個錯誤)

java.lang.ClassNotFoundException: xxx.yyy.zzz.MyTest 
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:513) 
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429) 
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417) 
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107) 
at java.lang.ClassLoader.loadClass(Unknown Source) 
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:143) 
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67) 
at java.lang.ClassLoader.loadClass(Unknown Source) 
at java.lang.Class.forName0(Native Method) 
at java.lang.Class.forName(Unknown Source) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:133) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:39) 
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:217) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:59) 
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32) 
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:31) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
at java.lang.reflect.Constructor.newInstance(Unknown Source) 
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31) 
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24) 
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57) 
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29) 
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57) 
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62) 
at org.eclipse.pde.internal.junit.runtime.PlatformUITestHarness$1.run(PlatformUITestHarness.java:47) 
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35) 
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135) 
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4140) 
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3757) 
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696) 
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660) 
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494) 
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674) 
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) 
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667) 
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) 
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) 
at org.eclipse.pde.internal.junit.runtime.NonUIThreadTestApplication.runApp(NonUIThreadTestApplication.java:54) 
at org.eclipse.pde.internal.junit.runtime.UITestApplication.runApp(UITestApplication.java:41) 
at org.eclipse.pde.internal.junit.runtime.NonUIThreadTestApplication.start(NonUIThreadTestApplication.java:48) 
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) 
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) 
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) 
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) 
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) 
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) 
at org.eclipse.equinox.launcher.Main.run(Main.java:1410) 
at org.eclipse.equinox.launcher.Main.main(Main.java:1386) 

我與圖書館配置的Test.Util在運行系統下類路徑的MANIFEST.MF和出口這些插件的每一個包。在Eclipse中,正確的庫從TestCase鏈接。

我還使用Bootstrapping與JUnit-Rule而不是@RunWith,但它導致相同的ClassNotFoundException。問題沒有改變。

我現在嘗試了很多東西 - 重新配置插件測試的運行配置,在Manifest,Lazy/Not-Lazy中設置ClassPath:。\,併爲PluginTest和測試設置Buddy-ClassLoading。 UTIL的插件。

經過幾個小時的網絡搜索和搜索之後,我仍然不知道爲什麼Powermock會導致這個異常,如果它從測試插件中提取到第三個插件中,以及我如何完成這項工作。我目前無法說我的應用程序中是否有錯誤配置。

任何遇到過相同或類似問題或得到了很好解決方案的人?

回答

1

我已經刪除了我以前的評論,因爲我成功地使用存儲在單個插件中的PowerMock庫運行pde插件測試。 用你的例子來回答你的問題,你需要在你的Test.Util中添加下面一行(你不應該使用upercase作爲插件id)MANIFEST。MF

Eclipse-BuddyPolicy: registered 

然後,如果你正在使用PluginTest插件是一個簡單的插件添加下面一行在它的MANIFEST.MF

Eclipse-RegisterBuddy: Test.Util 

如果您PluginTest是該包的片段PluginObject那麼你就必須在PluginObject清單的主機包中添加上一行。 希望這有助於;)

3

「註冊」的政策並沒有幫助我的情況下,我也不想註冊每個插件與util插件。對我來說,解決方案是在「Test.Util」聲明:

Eclipse的BuddyPolicy:依賴,註冊,全球,應用

,這使得更多或更少的可用的所有類PowerMockito。

1

您需要一個Powermock版本,它具有適當的OSGI清單和OSGI依賴關係。現在您可以試試我的小型項目,其中包含Powermock 1.5.4的P2更新站點。請參閱https://code.google.com/p/powermock/ OSGI部分(直接鏈接:https://code.google.com/p/powermock-osgi)。

在OSGI環境中,您可以使用只處理包含在導出包中的Powermock的類。在我的P2更新的網站,你會發現一個Powermock,其中有:

Eclipse-BuddyPolicy: global,ext,boot 

這basicly意味着,任何導出的包將是Powermock訪問。仍然必須導出測試的軟件包。如果您不想公開包中的所有包,則仍然可以在清單中使用X-Friends指令。你用Powermock作爲X-Friend出口包裝,這就是全部。

UPDATE: 答案CHRISS的問題:

Interesing,你能解釋一下爲什麼PowerMock是唯一能夠操縱 導出類?我目前的理解是,在運行時,所有 程序包都是可見的,只有在構建/編譯時才重要。

如果您使用Class.forName()在OSGI中獲取類運行時,您將使用您的捆綁類加載器來獲取您的名稱的類。這個bundle classloader只能看到導入包中的類。 Powermock包具有動態導入功能,但Powermock包的類加載器仍將只能看到任何包的任何導出包中的類。

如果你想知道你的類從哪裏來,哪個包輸出它,那麼你將能夠獲取該包的類加載器,並從該類加載器中獲得搜索到的類。但這當然相當複雜,這意味着,Powermock包需要一些hacky魔法類加載器,它隱藏了這個細節,但是這樣的東西不存在。

詳見http://olegz.wordpress.com/2008/11/05/osgi-and-classforname/

+1

Interesing,你能解釋一下爲什麼PowerMock是唯一能夠操縱導出類?我目前的理解是,在運行時,所有包都是可見的,只有在構建/編譯時才重要。 – Chriss

+1

看到我的更新,你就會明白。 –

+1

你可以看看這個:http://stackoverflow.com/questions/22456767/noclassdeffounderror-org-ham-ham-rest-matchers-using-powermock-osgi – Chriss