Mockito 无法在 Java 17 中模拟 Random

Kur*_*rru 8 java mockito java-17

尝试将我的项目从 Java 11 更新到 Java 17,并在特定测试中从 Mockito 收到意外错误。

mock(java.util.Random.class);
Run Code Online (Sandbox Code Playgroud)

投掷

Feb 04, 2022 3:07:01 PM com.google.inject.internal.MessageProcessor visit
INFO: An exception was caught and reported. Message: java.lang.IllegalAccessException: class 
    net.bytebuddy.description.annotation.AnnotationDescription$ForLoadedAnnotation cannot access interface
    jdk.internal.util.random.RandomSupport$RandomGeneratorProperties (in module java.base) 
    because module java.base does not export jdk.internal.util.random to unnamed module @2f54a33d
org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class java.util.Random.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.


Java               : 17
JVM vendor name    : Oracle Corporation
JVM vendor version : 17.0.2+8-86
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 17.0.2+8-86
JVM info           : mixed mode, sharing
OS name            : Mac OS X
OS version         : 12.1
Run Code Online (Sandbox Code Playgroud)

不知道为什么 Mockito 在这个测试中失败了。

Lak*_*gha 9

这里的问题是mockito(通过ByteBuddy)试图在运行时使用不可访问的类型(通过反射)。从 Java 9 开始,并非所有模块都可以访问,除非您显式导出/打开它们。

由于这是一个运行时问题,您可以添加--add-opens为 JVM arg/CLI 选项以使此类型可访问。

根据此处的Oracle 指南,--add-opens执行以下操作。

如果必须允许类路径上的代码进行深度反射以访问非公共成员,请使用 --add-opens 运行时选项。

如果您还想导出编译时可用的内部类型,您可以使用--add-exports.

解决您的具体问题;使用以下内容。

--add-opens java.base/jdk.internal.util.random=ALL-UNNAMED

ALL-UNNAMED意味着指定的包在整个代码库中可用。

然而,嘲笑不属于你的类型并不是一个好的做法。也许,如果有替代方案,您可以简化此操作。

  • `mock(Random.class, withSettings().withoutAnnotations())` 也对我有用 (9认同)

Kur*_*rru 9

这个特殊问题也可以使用以下方法解决:

mock(SecureRandom.class, withSettings().withoutAnnotations())
Run Code Online (Sandbox Code Playgroud)