运行 Eclipse RCP 项目中的普通 JUnit + Mockito 时出现 SecurityException
SecurityException when running plain JUnit + Mockito in Eclipse RCP Project
我有一个带有多个插件的 Eclipse RCP 项目。我正在编写纯 JUnit 测试(不依赖于 Eclipse/UI)作为被测插件的单独片段。
当使用 Mockito 并尝试从另一个插件模拟接口(已正确导出;我可以在我的代码中使用该接口)时,我得到一个与 class 签名相关的 SecurityException:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: interface ch.sbb.polar.client.communication.inf.service.IUserService
Mockito can only mock visible & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.withBefores(JUnit45AndHigherRunnerImpl.java:27)
[...]
Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238)
[...]
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[...]
Caused by: java.lang.SecurityException: Signers of 'ch.sbb.polar.client.communication.inf.service.IUserService$$EnhancerByMockitoWithCGLIB$$a8bfe723' do not match signers of other classes in package
at java.lang.ClassLoader.checkPackageSigners(ClassLoader.java:361)
at java.lang.ClassLoader.defineClass(ClassLoader.java:295)
... 40 more
当我 运行 测试 "JUnit Plugin tests" 时,即使用 OSGi 环境时,一切都按预期工作。但由于速度原因,我想使用普通的 JUnit 执行;在class测试中,我不需要OSGi环境。
有人知道这样做的方法吗?
如评论中所述,根本原因是 Mockito 的 Eclipse Orbit 包(我已将其添加到我的目标平台)已签名,并且由于底层 CGLIB 中的错误,您无法模拟未签名classes/interfaces 带有签名的 Mockito。
参见https://code.google.com/p/mockito/issues/detail?id=393 for the most detailed description. The bug is fixed in CGLIB head, but has not yet appeared in a release。 Mockito 仅使用已发布的版本作为依赖项,因此修复程序尚未在 Mockito 中,具有未知的(对我来说)时间表,因为这将在什么时候出现。
解决方法:在单独的包中提供未签名的 Mockito
解决方法是将 Mockito JAR(及其依赖项)打包到它自己的包中并导出必要的 API 包。
当使用 Maven Tycho、JUnit、Hamcrest 和 Mockito 时,我能够完成这项工作并正确解决所有依赖项/类路径/类加载器问题的唯一方法是以下方法:
使用 pom.xml 中的以下条目创建 Maven 模块:
<packaging>eclipse-plugin</packaging>
[...]
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
</dependency>
</dependencies>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-test-libs</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>lib</outputDirectory>
<stripVersion>true</stripVersion>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
在 MANIFEST.MF 中使用以下条目:
Bundle-ClassPath: lib/mockito-core.jar,
lib/objenesis.jar
Export-Package: org.mockito,
org.mockito.runners
Require-Bundle: org.junit;bundle-version="4.11.0";visibility:=reexport,
org.hamcrest.library;bundle-version="1.3.0";visibility:=reexport,
org.hamcrest.core;bundle-version="1.3.0";visibility:=reexport
最后在您的单元测试片段中,将这个新包添加为依赖项。
我 运行 遇到了同样的问题,并且能够通过使用更新的 Orbit 存储库解决它,该存储库提取 Mockito 2.x:
http://download.eclipse.org/tools/orbit/downloads/drops/R20181128170323/?d
此存储库包含 uses Byte Buddy instead of CGLIB.
的 Mockito 2.23.0
在我的目标中,我只是从上面的 Orbit 存储库中提取 mockito-core 2.23.0
和 Byte Buddy Java Agent 1.9.0
。
<unit id="org.mockito" version="2.23.0.v20181106-1534"/>
<unit id="org.mockito.source" version="2.23.0.v20181106-1534"/>
<unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
<unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>
我有一个带有多个插件的 Eclipse RCP 项目。我正在编写纯 JUnit 测试(不依赖于 Eclipse/UI)作为被测插件的单独片段。
当使用 Mockito 并尝试从另一个插件模拟接口(已正确导出;我可以在我的代码中使用该接口)时,我得到一个与 class 签名相关的 SecurityException:
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: interface ch.sbb.polar.client.communication.inf.service.IUserService
Mockito can only mock visible & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.withBefores(JUnit45AndHigherRunnerImpl.java:27)
[...]
Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238)
[...]
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[...]
Caused by: java.lang.SecurityException: Signers of 'ch.sbb.polar.client.communication.inf.service.IUserService$$EnhancerByMockitoWithCGLIB$$a8bfe723' do not match signers of other classes in package
at java.lang.ClassLoader.checkPackageSigners(ClassLoader.java:361)
at java.lang.ClassLoader.defineClass(ClassLoader.java:295)
... 40 more
当我 运行 测试 "JUnit Plugin tests" 时,即使用 OSGi 环境时,一切都按预期工作。但由于速度原因,我想使用普通的 JUnit 执行;在class测试中,我不需要OSGi环境。
有人知道这样做的方法吗?
如评论中所述,根本原因是 Mockito 的 Eclipse Orbit 包(我已将其添加到我的目标平台)已签名,并且由于底层 CGLIB 中的错误,您无法模拟未签名classes/interfaces 带有签名的 Mockito。
参见https://code.google.com/p/mockito/issues/detail?id=393 for the most detailed description. The bug is fixed in CGLIB head, but has not yet appeared in a release。 Mockito 仅使用已发布的版本作为依赖项,因此修复程序尚未在 Mockito 中,具有未知的(对我来说)时间表,因为这将在什么时候出现。
解决方法:在单独的包中提供未签名的 Mockito
解决方法是将 Mockito JAR(及其依赖项)打包到它自己的包中并导出必要的 API 包。
当使用 Maven Tycho、JUnit、Hamcrest 和 Mockito 时,我能够完成这项工作并正确解决所有依赖项/类路径/类加载器问题的唯一方法是以下方法:
使用 pom.xml 中的以下条目创建 Maven 模块:
<packaging>eclipse-plugin</packaging>
[...]
<dependencies> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.10.19</version> </dependency> </dependencies>
[...]
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-test-libs</id> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>lib</outputDirectory> <stripVersion>true</stripVersion> <includeScope>runtime</includeScope> </configuration> </execution> </executions> </plugin>
在 MANIFEST.MF 中使用以下条目:
Bundle-ClassPath: lib/mockito-core.jar, lib/objenesis.jar Export-Package: org.mockito, org.mockito.runners Require-Bundle: org.junit;bundle-version="4.11.0";visibility:=reexport, org.hamcrest.library;bundle-version="1.3.0";visibility:=reexport, org.hamcrest.core;bundle-version="1.3.0";visibility:=reexport
最后在您的单元测试片段中,将这个新包添加为依赖项。
我 运行 遇到了同样的问题,并且能够通过使用更新的 Orbit 存储库解决它,该存储库提取 Mockito 2.x:
http://download.eclipse.org/tools/orbit/downloads/drops/R20181128170323/?d
此存储库包含 uses Byte Buddy instead of CGLIB.
的 Mockito 2.23.0在我的目标中,我只是从上面的 Orbit 存储库中提取 mockito-core 2.23.0
和 Byte Buddy Java Agent 1.9.0
。
<unit id="org.mockito" version="2.23.0.v20181106-1534"/>
<unit id="org.mockito.source" version="2.23.0.v20181106-1534"/>
<unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/>
<unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/>