运行纯JUnit+;EclipseRCP项目中的Mockito

运行纯JUnit+;EclipseRCP项目中的Mockito,junit,eclipse-plugin,eclipse-rcp,mockito,osgi-fragment,Junit,Eclipse Plugin,Eclipse Rcp,Mockito,Osgi Fragment,我有一个带有多个插件的EclipseRCP项目。我正在编写简单的JUnit测试(与Eclipse/UI没有依赖关系),作为测试插件的单独片段 当使用Mockito并尝试从另一个插件(正确导出;我可以在我的代码中使用该接口)模拟接口时,我得到一个与类签名相关的SecurityException: org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: interface ch.sbb.polar.

我有一个带有多个插件的EclipseRCP项目。我正在编写简单的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环境


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

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

有关最详细的说明,请参阅。该错误已在中修复,但已修复。Mockito只使用已发布的版本作为依赖项,因此修复程序还没有在Mockito中,并且(对我来说)有一个未知的时间线,因为这将在何时出现

解决方法:在单独的包中提供未签名的Mockito 解决方法是将Mockito JAR(及其依赖项)打包到自己的包中,并导出必要的API包

在使用Maven Tycho、JUnit、Hamcrest和Mockito时,我唯一能够正确解决所有依赖项/类路径/类加载器问题的方法是:

  • 使用pom.xml中的以下条目创建Maven模块:

    <packaging>eclipse-plugin</packaging>
    
  • 最后,在单元测试片段中,添加这个新包作为依赖项


我遇到了同样的问题,通过使用最近的Orbit存储库解决了这个问题,该存储库支持Mockito 2.x:

此存储库包含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"/>


根据您使用的Mockito版本,您可能会遇到这种情况。@Rüdiger是的,我认为您是对的。我在研究中也发现了这个bug。我现在正在尝试一种变通方法,如果可行的话,我会将其作为答案发布。但是我还是很高兴其他人能提供任何有效的解决方案。你有没有检查过Mockito的新版本,包括固定的CGLIB?似乎还没有新版本。我已经读到Mockito只使用官方的cglib版本,而带有所谓补丁的版本还没有正式发布(尽管补丁被拉到了主存储库中)
<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>
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
<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"/>