【问题标题】:Java modules: accessibility problems for Mockito 2.20.0Java 模块:Mockito 2.20.0 的可访问性问题
【发布时间】:2018-05-31 23:51:22
【问题描述】:

我正在从 Java 8 迁移到 Java 10,并且我正在运行我的测试,该测试现在由于包保护类而失败。构建在 maven 3.5.4 + Oracle JDK 10.0.2 下运行:

  • maven-compiler-plugin 3.7.0 + asm 6.2
  • maven-surefire-plugin 2.22.0 + asm 6.2 + junit 5.2.0
  • 编译器/surefire 都需要 asm 6.2,因为这些插件使用的 ASM 版本存在错误。
  • mockito-core 2.20.0(但之前使用的是 2.20.0 和 Java 8)。
  • Eclipse 光子 R

该项目可以在这里找到ide-bugs.zip(它位于 Eclipse 论坛,因为我已经为另一个问题制作了这个Topic on Eclipse,这次是 Eclipse 的模块出现本地错误)。

测试非常简单:我们尝试以不同的访问级别模拟不同的类 - 所有这些都在 Java 8 中工作。

  1. 包保护类
  2. 公共类但未导出,未打开
  3. 公共类未导出但对 Mockito 开放
  4. 公共类未导出但对所有人开放
  5. 包保护类未导出但打开到 Mockito
  6. 包保护类未导出但对所有人开放

在 Java 8 中,情况 1、5 和 6 是相同的(访问受保护的包)。情况2、3、4相同(访问公共)。

测试失败,因为 Mockito 不能:

  • 类 org.mockito.codegen.NotExportedOpenToMockitoProtected$MockitoMock$117073031 无法访问其超类 nodatafound.mjpmsuc.withopens.NotExportedOpenToMockitoProtected
  • class org.mockito.codegen.NotExportedNotOpenedPublic$MockitoMock$365628885(在未命名的模块@0x3f07b12c)不能访问类nodatafound.mjpmsuc.internal.NotExportedNotOpenedPublic(在模块nodatafound.mockito_jpms_usecase),因为模块nodatafound.mockito_jpms_use内部未命名模块@0x3f07b12c

Mockito 实际上有一个 Automatic-Module-Name 但被视为未命名的模块,因为所有 jar 都在一个大的“未命名模块”的类路径中找到。

虽然我可以从受包保护的包迁移到非导出包,但我不明白如何解决使我的接口/类对其他模块不可见的问题?

[edit] 一个月后更新插件/依赖的版本,没有结果。

【问题讨论】:

    标签: java mockito maven-3 java-module java-10


    【解决方案1】:

    我在这里找到了我的问题的部分答案:https://blog.codefx.org/java/java-module-system-tutorial/#Open-Packages-And-Modules

    • Mockito 正在使用反射从模块或类路径访问类。
    • Mockito 位于“未命名模块”中,因为 Maven 将其添加到类路径而不是模块路径中。这就解释了为什么 opens package to org.mockito 永远不起作用:没有 org.mockito 模块。
    • Maven Surefire 不关心模块的“打开”以允许 Mockito 访问它。
    • Mockito (不再?)能够模拟非私有和非最终类类。无论如何,包保护类都是私有的。错误相当明确:Mockito 创建了一个扩展包保护类的类,但现在失败了(它以前可以工作,但这可能是因为 Mockito 在与被模拟的包相同的包中创建了该类)。

    尽管如此,这在每个模块的 pom.xml 中给出了一个有问题的配置:

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <argLine>    
      --add-opens nodatafound.mockito_jpms_usecase/nodatafound.mjpmsuc=ALL-UNNAMED
            </configuration>      
          </plugin>
    

    我们需要显式添加 opens 到一个未命名的模块。这不应该在 module-info.java 中完成,因为它会将模块暴露给 all 其他反对封装的模块或 jar。

    这是有问题的,因为:

    • 您需要在 pom.xml 中为每个包指定它。
    • 它给我更喜欢简单的安全配置增加了额外的负担。
    • 您没有来自 IDE 的验证; Eclipse 将验证 module-info.java 标记无效包。
    • m2e 没有将必要的&lt;argLine /&gt; 传递给 Eclipse JUnit 插件,从而导致 Eclipse 中的测试失败。

    maven 方法(在 Eclipse 中也是如此,据我所知可能还有 Gradle)不允许为测试添加额外的模块信息;例如:让测试依赖是模块化的(这可以使用每个源模块的专用测试模块来完成,就像 Eclipse 对插件测试所做的那样)。

    【讨论】:

      猜你喜欢
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      • 1970-01-01
      相关资源
      最近更新 更多