5

我有一个带有多个插件的 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 环境。

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

4

2 回答 2

5

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

有关最详细的说明,请参阅https://code.google.com/p/mockito/issues/detail?id=393 。该错误已在CGLIB 头中修复,但尚未出现在版本中。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
    
  • 最后在您的单元测试片段中,将此新捆绑包添加为依赖项。

于 2015-02-19T10:15:57.117 回答
0

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

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

此存储库包含使用 Byte Buddy 而不是 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"/>
于 2019-02-24T19:33:47.410 回答