我已成功 JUnit 4.12 + Hamcrest 1.3 + Mockito 2.8.47 在 Eclipse中工作因此,当我将它们作为依赖项添加时,我的测试将会运行。
(我这样做的方法是使用p2-maven-plugin捆绑以下内容 从Maven Central到插件/功能的工件,并通过P2提供它们:
junit 4.12
org.mockito.mockito-core 2.8.47
org.hamcrest.all 1.3.0
将插件作为依赖项添加到我的测试片段中进行测试 在Eclipse中运行。
但是,相同片段的 Tycho 版本将失败 以下消息:
java.lang.LinkageError: loader constraint violation: loader (instance of org/eclipse/osgi/internal/loader/EquinoxClassLoader) previously initiated loading for a different type with name "org/hamcrest/Matcher"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.defineClass(ModuleClassLoader.java:273)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.defineClass(ClasspathManager.java:632)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findClassImpl(ClasspathManager.java:586)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClassImpl(ClasspathManager.java:538)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:525)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:325)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:345)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:423)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:372)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:364)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:12)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)
所以似乎其他一些插件正在加载包
我的片段之前的org.hamcrest.Matcher
。这可能是应该的
到周围的进口/出口/部分进口/部分出口混乱
JUnit / Hamcrest / Mockito设置。
有没有人有一个想法 - 甚至更好:一个工作的例子 - 如何 让三个组件在IDE中一起工作(快速 检查测试是否运行)和Tycho(用于构建期间的检查)?
答案 0 :(得分:1)
似乎加载器想要捆绑中的依赖项。
但我猜你还没有将你的测试库放在一个包中。
您可以尝试将它们添加到产品的依赖项中,以了解它的反应。
答案 1 :(得分:0)
背景
问题的根源在于,org.junit
已经依赖于 org.hamcrest.core
。因此,当您的测试插件依赖于 org.hamcrest.all
(包含 hamcrest-core 和所有其他 hamcrest 工件的所有内容)时,在 hamcrest-core 中指定的所有类都存在两次。一次在 hamcrest-core 包中,一次在 hamcrest-all 包中,这就是您收到链接错误的原因。
如果您在 Eclipse 的 Manifest-Editor 中打开 org.junit
的 Manifest 并转到“Dependencies”选项卡,它应该会在“Required Plug-ins”部分显示 org.hamcreast.core
和 {{ 1}} 应该重新导出。或者在原始清单中它应该是这样的:
org.hamcreast.core
解决方案 1 - 添加 hamcrest 子模块
我没有将包含 Require-Bundle: org.hamcrest.core;bundle-version="1.3.0";visibility:=reexport
的所有 hamcrest 模块作为依赖项添加到我的 Eclipse 测试包/项目(通过“Require-Bundle”),而是添加了我需要的 hamcrest 子模块,除了 hamcrest -core(因为在我的情况下它已经重新导出了)。对我来说,hamcrest-library 就足够了。
可用的 hamcrest 子模块是(根据 org.hamcrest:hamcrest-parent pom,可以在这里找到:https://repo1.maven.org/maven2/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom):
创建包含所需包的 p2-Repo
当使用 Maven 和 'org.reficio:p2-maven-plugin' 构建包含上述测试包的 p2-repo 时,maven-artifacts 到 OSGi-bundles 的转换不会产生完全工作的结果默认情况下。
将 maven 模块转换为完整的 OSGi 包主要包括配置 MANIFEST.MF 以包含正确的条目。为此,p2-maven-plugin 使用“bnd 工具”。
默认情况下,当该模块转换为 OSGi 包时,maven 模块的所有 maven 依赖项提供的 Java 包作为可选 hamcrest.all
添加。
就我而言,这导致 Imported-package
包仅通过其 MANIFEST.MF 中的 org.hamcrest.library
引用来自 hamcrest-core 的包。
但不幸的是,只指定了这个,Equinox-ClassLoader 在测试运行时没有从 hamcrest-core 中找到类并抛出相应的异常。也许这也是因为hamcrest-core和hamcrest-library有一个包“org.hamcrest”,bnd-tools又把一个bundle的导出包添加到了导入包中。
我的解决方案是分别指示 Import-Package
和 bnd-tools 将 org.reficio:p2-maven-plugin
作为“Require-Bundle”添加到 hamcrest-library 的清单中。为此,需要将下面显示的指令元素添加到用于构建 p2 的 org.hamcrest.core
中“p2-maven-plugin”的执行配置中的 org.hamcrest:hamcrest-library
的工件元素中-repo:
pom.xml
如果使用 hamcrest-library 以外的 hamcrest 子模块,则指令需要类似,对应于其 pom 中列出的依赖项。
编辑
Eclipse Orbit 提供 <artifact>
<id>org.hamcrest:hamcrest-library:1.3</id>
<instructions>
<Require-Bundle>org.hamcrest.core</Require-Bundle>
</instructions>
</artifact>
、org.hamcrest.library
和 org.hamcrest.integrator
捆绑包,这些捆绑包将 org.hamcrest.core 作为必需捆绑包(如有必要):
https://download.eclipse.org/tools/orbit/downloads/
附录 最后第一个解决方案导致了 SecurityException:
org.hamcrest.generator
这是一个已知问题。以下两种解决方案可避免此问题,并在 Tycho 构建期间和在 Eclipse 中正常工作。
解决方案 2 - 使用插件捆绑 hamcrest 子模块 jar 另一种方法是下载所需 hamcrest 子模块的 jar 并将其直接与 Eclipse 插件捆绑,就像这里描述的那样: https://www.vogella.com/tutorials/Hamcrest/article.html#hamcrest_eclipse
要将 jar 与插件捆绑在一起,请将其包含在项目中并将其添加到插件类路径中。转到 Manifest-Editor 的 Runtime-Tab 并单击 Classpath 部分中的 java.lang.SecurityException: class "org.hamcrest.Matchers"'s signer information does not match signer information of other classes in the same package
并选择 jar。这应该将 jar 添加到 .classpath、MANIFEST.MF 和 build.properties 文件中。
确保 jar 包含在其他插件依赖项(包括 hamcrest-core)之前,如上述教程中所述。
如果 hamcrest 应该在多个测试项目/片段中使用,请将 jar 添加到所有其他测试项目所依赖的测试插件中。
解决方案 3 - 使用 org.hamcrest 2.x 由于 hamcrest-2 只有一个 org.hamcrest jar/artifact 包含来自 hamcrest 的所有内容。使用 hamcrest 2 避免了所有问题,是我首选的解决方案。除了更改了 hamcrest 的包装外,API 没有中断,因此只包含 org.hamcrest 就足够了: https://github.com/hamcrest/JavaHamcrest/releases/tag/v2.1
为了创建包含 Add...
-2.2 的 p2-repo,以下 sippet 必须包含在 org.hamcrest
执行的 configuration
-artifacts
元素中pom.xml:
p2-maven-plugin
必须将 IU <artifact>
<id>org.hamcrest:hamcrest-core:2.2</id>
<instructions>
<Require-Bundle>org.hamcrest;bundle-version="2.2.0";visibility:=reexport</Require-Bundle>
</instructions>
</artifact>
<artifact>
<id>org.hamcrest:hamcrest:2.2</id>
</artifact>
2.2 和 org.hamcrest.core
包含在目标平台中,才能使它们可用于 Eclipse 和 during 中的插件。所有依赖于 org.hamcrest
的插件现在也有 org.junit
可用。
这种方法有效,因为 org.hamcrest
仍然存在于第 2 版流中,即使它已被弃用且为空。它的唯一目的是将构建系统重定向到新的 org.hamcrest.core
-2.x jar/artifact。因此 org.hamcrest
-2.2 指定了一个编译依赖
org.hamcrest.core
-2.2 在其 pom.xml 中。不幸的是,org.hamcrest
并没有直接将其转换为清单中 org.hamcrest 的捆绑需求,但上面的 sippet 强制执行了这一点。
因为 p2-maven-plugin
需要最低版本为 1.3(但没有上限)的 org.hamcrest.core 包,所以它使用当前的 org.junit
-2.2 。 org.hamcrest.core
-2.2 再次需要 org.hamcrest.core
-2.2 并重新导出它。这使得 org.hamcrest
最后使用 org.junit
-2.2 并且因为 org.junit 重新导出 org.hamcrest
它也立即为所有依赖的插件提供 hamcrest-core
-2.2。< /p>
注意
如果您想使用 jar 的不同变体,请不要忘记清除(意味着在驱动器上删除)Maven(在 org.hamcrest
和 Eclipse PDE(在 <your-home>/.m2/repository/p2/osgi/bundle/
)之间。否则你将永远使用第一个,因为相同版本的jar不会更新。