Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito can not mock Random in Java 17

Trying to update my project from Java 11 to Java 17 and got an unexpected error from Mockito in a specific test.

mock(java.util.Random.class);

Throws

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

Not sure why Mockito is failing on this test.

like image 737
Kurru Avatar asked Apr 15 '26 15:04

Kurru


2 Answers

This particular issue was also resolvable using:

mock(SecureRandom.class, withSettings().withoutAnnotations())
like image 134
Kurru Avatar answered Apr 17 '26 06:04

Kurru


The issue here is mockito (via ByteBuddy) is trying to use an inaccessible type at runtime (via reflection). From Java 9 onwards, not all modules are accessible unless you explicitly export/open them.

As this is a runtime issue, you can add --add-opens as a JVM arg/CLI option to make this type accessible.

As per the Oracle guide here, --add-opens does the following.

If you have to allow code on the classpath to do deep reflection to access nonpublic members, then use the --add-opens runtime option.

If you want to export internal types available in compile time as well, you can use --add-exports.

To solve your specific issue; use the following.

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

ALL-UNNAMED means, a specified package is available in the entire codebase.

However, mocking types that don't belong to you is not a good practice. Maybe, you can simplify this if there's an alternative.

like image 30
Laksitha Ranasingha Avatar answered Apr 17 '26 06:04

Laksitha Ranasingha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!