在Eclipse RCP项目中运行普通JUnit + Mockito时的SecurityException

问题描述 投票:5回答:2

我有一个带有多个插件的Eclipse RCP项目。我正在编写简单的JUnit测试(不依赖于Eclipse / UI)作为测试插件的单独片段。

当使用Mockito并尝试从另一个插件模拟一个接口(正确导出;我可以在我的代码中使用该接口)时,我得到一个与类签名相关的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$1.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插件测试”运行时,即使用OSGi环境时,一切都按预期工作。但是我想因速度而使用普通的JUnit执行;在被测试的类中,我不需要OSGi环境。

有人知道这样做的方法吗?

junit eclipse-plugin eclipse-rcp mockito osgi-fragment
2个回答
5
投票

正如评论中提到的,根本原因是Mockito的Eclipse Orbit包(我已经添加到我的目标平台)被签名,并且由于底层CGLIB中的一个错误,你不能使用a来模拟未签名的类/接口。签下了Mockito。

有关最详细的说明,请参阅https://code.google.com/p/mockito/issues/detail?id=393。该错误在CGLIB head修复,但有not yet appeared in a release。 Mockito只使用已发布的版本作为依赖项,因此该修复程序尚未在Mockito中,并且具有未知(对我而言)的时间轴,就像它将在何时一样。

Workaround: Provide unsigned Mockito in separate bundle

解决方法是将Mockito JAR(及其依赖项)打包到自己的bundle中并导出必要的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
  • 最后在单元测试片段中,将此新包添加为依赖项。

0
投票

我遇到了同样的问题,并且能够通过使用更新的Orbit存储库来解决它,该存储库提取了Mockito 2.x:

http://download.eclipse.org/tools/orbit/downloads/drops/R20181128170323/?d

此存储库包含Mockito 2.23.0,其中包含uses Byte Buddy instead of CGLIB

在我的目标中,我只是从上面的Orbit存储库中拉出mockito-core 2.23.0Byte 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"/>
© www.soinside.com 2019 - 2024. All rights reserved.