Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@SpykBean on Spring Data Repository doesn't work anymore with JDK16+ #65

Closed
ajgassner opened this issue Sep 2, 2021 · 8 comments
Closed

Comments

@ajgassner
Copy link

ajgassner commented Sep 2, 2021

Hi,

I already stumbled over @jnizet commit b6dbc1b

But in our case @SpykBean isn't working with following configuration:

  • openjdk version "16.0.1" 2021-04-20
  • Kotlin 1.5.21
  • Spring Boot 2.5.3
  • SpringMockk 3.0.1

Simple data repository spy:

    @SpykBean
    private lateinit var documentRepository: DocumentRepository

Exception when running the test:

...
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'documentRepository': Post-processing of FactoryBean's singleton object failed; nested exception is java.lang.IllegalAccessException: class io.mockk.impl.InternalPlatform$copyFields$1 cannot access a member of class java.lang.reflect.Proxy (in module java.base) with modifiers "protected"
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 68 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'documentRepository': Post-processing of FactoryBean's singleton object failed; nested exception is java.lang.IllegalAccessException: class io.mockk.impl.InternalPlatform$copyFields$1 cannot access a member of class java.lang.reflect.Proxy (in module java.base) with modifiers "protected"
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:119)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1884)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1266)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:345)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 87 common frames omitted
Caused by: java.lang.IllegalAccessException: class io.mockk.impl.InternalPlatform$copyFields$1 cannot access a member of class java.lang.reflect.Proxy (in module java.base) with modifiers "protected"
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:385)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:687)
	at java.base/java.lang.reflect.Field.checkAccess(Field.java:1096)
	at java.base/java.lang.reflect.Field.get(Field.java:417)
	at io.mockk.impl.InternalPlatform$copyFields$1.invoke(InternalPlatform.kt:110)
	at io.mockk.impl.InternalPlatform$copyFields$1.invoke(InternalPlatform.kt:114)
	at io.mockk.impl.InternalPlatform.copyFields(InternalPlatform.kt:117)
	at io.mockk.impl.instantiation.AbstractMockFactory.spyk(AbstractMockFactory.kt:107)
	at com.ninjasquad.springmockk.SpykDefinition.createSpy(SpykDefinition.kt:75)
	at com.ninjasquad.springmockk.MockkPostProcessor.createSpyIfNecessary(MockkPostProcessor.kt:335)
	at com.ninjasquad.springmockk.MockkPostProcessor$SpyPostProcessor.postProcessAfterInitialization(MockkPostProcessor.kt:398)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:437)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1929)
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
	... 96 common frames omitted

The workaround is to switch to JDK <= 15.

Has anyone an idea to fix the issue?

@iliassk
Copy link

iliassk commented Dec 1, 2021

It doesn't seem to work on @RequestScope @SessionScope beans neither

@jnizet
Copy link
Member

jnizet commented Dec 3, 2021

Sorry folks. To be honest, I have no idea of how to deal with this issue. My guess is that it's actually a problem of MockK itself regarding spying proxies. If one of you could come up with a simple repro (as a github repo), maybe not even using SpringMockK, and could sublit this issue to MockK, that would be great.

@PavelPolyakov
Copy link

Also met this issue while trying to update to JDK17.

Are there any options to overcome this? I thought common to spy on repositories. I'm surprised that not that many people report that they have this problem. I don't see any relevant issue on mockk side.

One option I see is not to spy on the repositories ;) But it's said nowhere in the documentation, that one shall not do that.

@phillipuniverse
Copy link

phillipuniverse commented Feb 25, 2022

@jnizet I agree that this is almost certainly a mockk issue with proxy spies.

Another piece of information - for whatever reason the final exception masks the original exception:

java.lang.reflect.InaccessibleObjectException: Unable to make field protected java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.h accessible: module java.base does not "opens java.lang.reflect" to unnamed module @17550481

image

So it appears the new Java 17 strong encapsulation is what is actually breaking this. In 9-11 this just gave a warning, now it fails hard.

@ajgassner @PavelPolyakov a workaround is to add the --add-opens JVM flag to your test execution. In Gradle (build.gradle.kts):

tasks.test {
    jvmArgs = listOf("--add-opens=java.base/java.lang.reflect=ALL-UNNAMED")
}

Adding this for me causes my spied repositories to work just as before. My JVM:

openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment Temurin-17.0.2+8 (build 17.0.2+8)
OpenJDK 64-Bit Server VM Temurin-17.0.2+8 (build 17.0.2+8, mixed mode, sharing)

@jnizet
Copy link
Member

jnizet commented Feb 25, 2022

Thanks a lot @phillipuniverse , that's good information!

It would really be nice if you could open an issue, with a minimal repro, on the MockK repo, because it looks more and more like something that does not really come from SpringMockK.

@sergey-volkov-lm
Copy link

It seems to me, spring data is also involved in this issue. According to spring docs, java.lang.reflect.Proxy should not be used as proxy any more (by default) in favor of CGLib one (not official, but embedded in spring core).

@MarianPohling
Copy link

MarianPohling commented Nov 22, 2022

Any further progress on this issue? I just updated to java 17 and run into the same errors. So its seem to be still an issue :(

@jnizet
Copy link
Member

jnizet commented Dec 1, 2022

@MarianPohling The workaround explained above, and now described in the README, is the official solution from MockK

@jnizet jnizet closed this as completed Dec 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants