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:
- maven-compiler-plugin 3.7.0 + asm 6.2
- maven-surefire-plugin 2.22.0 + asm 6.2 + junit 5.2.0
- 两个 compiler/surefire 都需要 asm 6.2,因为这些插件使用的 ASM 版本中存在错误。
- mockito-core 2.20.0(但之前使用 2.20.0 和 Java 8)。
- 日食光子 R
项目可以在这里找到ide-bugs.zip (it is located at Eclipse forum because I've made this Topic on Eclipse另一个问题,这次 Eclipse 有模块的本地错误)。
测试非常简单:我们尝试模拟不同的 class,具有不同的访问级别 - 所有这些都在 Java 8.
中工作
- 包保护class
- public class 但未导出,未打开
- public class 未导出但打开到 Mockito
- public class 未导出但对所有人开放
- 包受保护class 未导出但已打开到 Mockito
- 包受保护class未导出但对所有人开放
在Java8中,情况1、5、6相同(访问包受保护)。情况2、3、4相同(访问public)。
测试失败,因为 Mockito 无法:
- class org.mockito.codegen.NotExportedOpenToMockitoProtected$MockitoMock$117073031 无法访问它的 superclass nodatafound.mjpmsuc.withopens.NotExportedOpenToMockitoProtected
- class org.mockito.codegen.NotExportedNotOpenedPublic$MockitoMock$365628885(在未命名模块@0x3f07b12c 中)无法访问 class nodatafound.mjpmsuc.internal.NotExportedNotOpenedPublic(在模块 nodatafound.mockito_jpms_usecase 中)因为模块 nodatafound.mockito_jpms_usecase 不导出 nodatafound.mjpmsuc.internal 到未命名模块 @0x3f07b12c
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 对插件测试所做的那样,使用每个源模块的专用测试模块来完成)。
我正在从 Java 8 迁移到 Java 10,我正在 运行 我的测试现在由于包保护 classes 而失败。构建是运行 under 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
- 两个 compiler/surefire 都需要 asm 6.2,因为这些插件使用的 ASM 版本中存在错误。
- mockito-core 2.20.0(但之前使用 2.20.0 和 Java 8)。
- 日食光子 R
项目可以在这里找到ide-bugs.zip (it is located at Eclipse forum because I've made this Topic on Eclipse另一个问题,这次 Eclipse 有模块的本地错误)。
测试非常简单:我们尝试模拟不同的 class,具有不同的访问级别 - 所有这些都在 Java 8.
中工作- 包保护class
- public class 但未导出,未打开
- public class 未导出但打开到 Mockito
- public class 未导出但对所有人开放
- 包受保护class 未导出但已打开到 Mockito
- 包受保护class未导出但对所有人开放
在Java8中,情况1、5、6相同(访问包受保护)。情况2、3、4相同(访问public)。
测试失败,因为 Mockito 无法:
- class org.mockito.codegen.NotExportedOpenToMockitoProtected$MockitoMock$117073031 无法访问它的 superclass nodatafound.mjpmsuc.withopens.NotExportedOpenToMockitoProtected
- class org.mockito.codegen.NotExportedNotOpenedPublic$MockitoMock$365628885(在未命名模块@0x3f07b12c 中)无法访问 class nodatafound.mjpmsuc.internal.NotExportedNotOpenedPublic(在模块 nodatafound.mockito_jpms_usecase 中)因为模块 nodatafound.mockito_jpms_usecase 不导出 nodatafound.mjpmsuc.internal 到未命名模块 @0x3f07b12c
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 对插件测试所做的那样,使用每个源模块的专用测试模块来完成)。