doc/md/jdk16-access-exceptions.md
On JDK 16 and above you may encounter InaccessibleObjectException or IllegalAccessException in the following known cases:
Some usages of mockkStatic on Java standard library classes, e.g.
mockkStatic(Instant::class)
every { Instant.now() } returns Instant.parse("2022-09-15T09:31:26.919Z")
java.time.format.DateTimeParseException: Text '2022-09-15T09:31:26.919Z' could not be parsed:
Unable to make private static java.time.Instant java.time.Instant.create(long,int) accessible:
module java.base does not "opens java.time" to unnamed module @4501b7af
Spying on Java standard library classes, e.g.
val socket = Socket()
val spy = spyk<Socket>(socket)
Note: this includes creating @SpyKBean on spring data repository instances, because they are instances of java.lang.reflect.Proxy in fact.
Error creating bean with name 'featureRepository': Post-processing of FactoryBean's singleton object failed;
nested exception is java.lang.IllegalAccessException: class io.mockk.impl.InternalPlatform
cannot access a member of class java.lang.reflect.Proxy (in module java.base) with modifiers "protected"
JDK 16 enforces strong encapsulation of standard modules. In practice this mean overriding accessibility modifiers in JDK classes (for example, privateMember.setAccessible(true)) is forbidden.
Add JVM argument --add-opens java.base/full.package.name=ALL-UNNAMED for each package you need to mock. Package name should be fully qualified.
Description: https://docs.oracle.com/en/java/javase/16/migrate/migrating-jdk-8-later-jdk-releases.html
Example for Gradle users:
tasks.test {
jvmArgs(
"--add-opens", "java.base/java.time=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
)
}
Example for Gradle users within an Android module:
android {
testOptions {
unitTests.all {
jvmArgs(
"--add-opens", "java.base/java.time=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
)
}
}
}
Example for Maven users:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-opens java.base/java.time=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
</argLine>
</configuration>
</plugin>