【问题标题】:NoClassDefFoundError: org/hamcrest/Matchers using PowerMock-OSGiNoClassDefFoundError: org/hamcrest/Matchers 使用 PowerMock-OSGi
【发布时间】:2014-03-17 14:18:59
【问题描述】:

当我将我的测试作为 OSGi 插件测试运行时,我得到 org.hamcrest.Matchers 的 NoClassDefFoundError,但是当我将它作为普通 JUnit 测试运行时,一切都按预期工作。我正在使用OSGi version of PowerMock 并在我的启动配置中拥有所有必要的依赖项。 我做错了什么?出于某种原因,Testrunner 似乎没有看到该课程。

编辑: 我创建了一个简化的示例项目,并发现问题仅在我在类声明中使用 @PrepareForTest(XXX.class) 时出现。


java.lang.NoClassDefFoundError: org/hamcrest/Matchers
    at eu.gemtec.commons.util.assertion.Assert.assertParamNotNull(Assert.java:107)
    at eu.gemtec.eagle.device.aastra.omaxi.core.system.model.impl.MessageHandleFactory.<init>(MessageHandleFactory.java:72)
    at eu.gemtec.eagle.device.aastra.omaxi.core.system.model.impl.TestMessageHandleFactory.setUp(TestMessageHandleFactory.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$LastRuleTestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:148)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:91)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    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.CoreTestApplication.run(CoreTestApplication.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:587)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:198)
    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(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    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)
Caused by: java.lang.ClassNotFoundException: org.hamcrest.Matchers
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:467)
    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(ClassLoader.java:356)
    at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:65)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    ... 52 more

【问题讨论】:

  • 在每种情况下你是如何运行它的。几乎 100% 肯定是类路径问题。
  • 当我将它作为插件测试运行时,我使用包含所有必需插件的运行配置。注意:我没有因为缺少依赖项而收到任何错误,它全部到位。我想这是一个类加载问题。
  • 那么,我假设您使用的是 Eclipse?您的项目没有显示错误这一事实并不意味着相同的库包含在您的运行/调试配置中。我会首先确保您的项目正在导出有问题的库,然后检查启动配置以确保它们显示出来。
  • 是的,我使用 Eclipse。当我启动测试时,我没有得到任何依赖错误,一切就绪。只有使用 Powermock 的测试无法访问 org.hamcrest.Matchers,同一套件中的所有其他测试都可以加载该类。
  • 查看测试的启动配置时,Classpath 选项卡中有什么?

标签: java osgi mockito powermock hamcrest


【解决方案1】:

如果你看一下 Powermock-osgi 的update site,你会注意到那里有 hamcrest 和 junit 包。然而,它们不是“正常的”官方发布的捆绑包,而是包装捆绑包,比官方发布的包更多。

如果您使用 Eclipse,则工作空间的捆绑池是共享的。使用符号名称和版本查找包。因此,您必须从 powermock-osgi 的更新站点添加 junit 和 hamcrest,并且您必须确定,在解析目标平台之前,您删除了所有工作区的所有捆绑池。

Powermock-OSGI site:

Tycho 和 Eclipse PDE 缓存基于符号名称和 版本。所以如果用户在任何时候都已经拥有了 4.11 版本的 Junit 过去,我们破解的powermock版本不会被拿走。

所以在 Eclipse 中第一次使用之前,用户必须删除 .metadata.plugins\org.eclipse.pde.core.bundle_pool 和 .metadata.plugins\org.eclipse.pde.core.external_libraries 在所有 特定 Eclipse 安装的工作区(查找捆绑包 跨工作区方式)。请确保,当您在 eclipse启动配置中的插件选项卡确实包含 Powermock 功能的 JUnit、Mockito 和 Hamcrest 插件,而不是 其他版本。在第一次使用第谷之前删除 .meta 来自 maven 本地存储库的 .cache 和 p2 文件夹

如果不是这样,请提供以下内容让我帮助您:

  • 您的目标文件为 XML
  • 测试片段清单和主机包清单
  • 您的 hamcrest 和 junit 捆绑包的大小 里面

如果您通过示例项目向https://code.google.com/p/powermock-osgi/ 提出问题,我会查看它。

编辑: 还有一件事。 OSGI 包中的 eu.gemtec.commons.util.assertion.Assert 类是否将 hamcrest 作为依赖项导入? eu.gemtec.commons.util.assertion 包导出了吗?

EDIT2: 事实证明,我的“被黑”powermock-osgi 版本的 hamcrest 没有将 org.hamcrest 导出为拆分包,这就是问题所在。更新站点的修复程序即将推出。见https://code.google.com/p/powermock-osgi/issues/detail?id=2#c4

EDIT3:http://powermock-osgi.googlecode.com/svn/updateSite/1.5.4.1http://powermock-osgi.googlecode.com/svn/updateSite/1.5.4.1为 Chriss 提供更新站点用于测试目的

更新:项目已自动迁移到 github。更新地址:https://raw.githubusercontent.com/liptga/powermock-osgi/master/update-site/1.5.6.0

项目地址:https://github.com/liptga/powermock-osgi

感谢克里斯帮助调查。

【讨论】:

  • 既然看起来有点复杂,i filed an issue 就像你说的那样。一旦有可用的解决方案,我将在此处发布。
  • 注意:org.hamcrest.library 不包含在 powermock-osgi 更新站点中。
  • 谢谢你的报告,我去看看。
猜你喜欢
  • 2016-11-21
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 2013-01-10
相关资源
最近更新 更多