Java 模块:Mockito 2.20.0 的可访问性问题

Java modules: accessibility problems for Mockito 2.20.0

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

项目可以在这里找到ide-bugs.zip (it is located at Eclipse forum because I've made this Topic on Eclipse另一个问题,这次 Eclipse 有模块的本地错误)。

测试非常简单:我们尝试模拟不同的 class,具有不同的访问级别 - 所有这些都在 Java 8.

中工作
  1. 包保护class
  2. public class 但未导出,未打开
  3. public class 未导出但打开到 Mockito
  4. public class 未导出但对所有人开放
  5. 包受保护class 未导出但已打开到 Mockito
  6. 包受保护class未导出但对所有人开放

在Java8中,情况1、5、6相同(访问包受保护)。情况2、3、4相同(访问public)。

测试失败,因为 Mockito 无法:

Mockito 实际上有一个 Automatic-Module-Name 但被视为未命名模块,因为所有 jar 都在 class 路径中找到一个大 "unnamed module".

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

[edit] 一个月后更新了 plugin/dependency 的版本,没有结果。

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

  • Mockito 正在使用反射从模块或 class 路径访问 classes。
  • Mockito 在 "unnamed module" 中,因为 Maven 将它添加到 class 路径而不是模块路径。这解释了为什么 opens package to org.mockito 永远不起作用:没有 org.mockito 模块。
  • Maven Surefire 不关心为了允许 Mockito 访问它而对模块的 "opens" 做出贡献。
  • Mockito(不再?)能够模拟非私有和非最终classes class。无论如何,受保护的包 class 都是私有的。错误是相当明确的:Mockito 创建了一个 class extending the package protected class,现在失败了(它以前工作过,但这可能是因为 Mockito 在同一个包中创建了 class比被嘲笑的那个)。

然而,这在每个模块的 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 中指定它。
  • 它给我更喜欢简单的 surefire 配置增加了额外的负担。
  • 您没有来自 IDE 的验证; Eclipse 将验证 module-info.java 标记无效包。
  • m2e 没有将必要的 <argLine /> 传递给 Eclipse JUnit 插件,导致 Eclipse 中的测试失败。

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