I have this Junit 5 test code:
@InjectMocks
ReportAssembler reportAssembler;
private ReportingReturnResponse reportingReturnResponse;
private ReturnReport returnReport;
private StaticPathLinkBuilder staticPathLinkBuilder;
@Test
public void testMergeReturnCompletesSuccessfully() {
ReportingResource reportResource = reportAssembler.mergeReturn(returnReport, this.reportingResource);
assertNotNull(reportResource.getReturnResource());
}
The called code:
public ReportingResource mergeReturn(ReturnReport returnReport, ReportingResource reportingResource) {
Link link = staticPathLinkBuilder.linkTo(
methodOn(ReturnController.class).getReturnById(
returnReport.getAccount().getId(),
returnReport.getReturn().getId())
).withSelfRel();
return reportingResource;
}
public LinkBuilder linkTo(Object dummyInvocation) {
LastInvocationAware lastInvocationAware = (LastInvocationAware) dummyInvocation;
MethodInvocation methodInvocation = lastInvocationAware.getLastInvocation();
StaticPathLinkBuilder staticPathLinkBuilder = getThis();
return staticPathLinkBuilder.linkTo(methodInvocation.getMethod(), methodInvocation.getArguments());
}
The line return staticPathLinkBuilder.linkTo(methodInvocation.getMethod(), methodInvocation.getArguments())
throws an exception Caused by: java.lang.IllegalArgumentException: Cannot subclass final class java.lang.reflect.Method
How I can solve it?
The stacktrace:
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class java.lang.reflect.Method: Common causes of this problem include using a final class or a non-visible class
at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:237)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:167)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.hateoas.server.core.DummyInvocationUtils.getProxyWithInterceptor(DummyInvocationUtils.java:207)
at org.springframework.hateoas.server.core.DummyInvocationUtils$InvocationRecordingMethodInterceptor.invoke(DummyInvocationUtils.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy3/jdk.proxy3.$Proxy81.getMethod(Unknown Source)
at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:56)
at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:42)
at com.assembler.ReportingAssembler.mergeReturn(ReportingAssembler.java:233)
at com.assembler.ReportingAssemblerReturnTest.testMergeReturnCompletesSuccessfully(ReportingAssemblerReturnTest.java:50)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class java.lang.reflect.Method
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:653)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:35)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:26)
at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:76)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:366)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:317)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407)
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:62)
at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:167)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.hateoas.server.core.DummyInvocationUtils.getProxyWithInterceptor(DummyInvocationUtils.java:207)
at org.springframework.hateoas.server.core.DummyInvocationUtils$InvocationRecordingMethodInterceptor.invoke(DummyInvocationUtils.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy3/jdk.proxy3.$Proxy81.getMethod(Unknown Source)
at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:56)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$ADlM6biV.invokeWithArguments(Unknown Source)
at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
at org.mockito.Answers.answer(Answers.java:90)
at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
... 6 more
You are using sensitive API, that is not intended for public use while it is public.
The library authors explain this in this GitHub issue.
They also suggest a workaround in the same github issue - use DummyInvocationUtils.getLastInvocationAware(...)
.
For your specific case, replace this:
LastInvocationAware lastInvocationAware = (LastInvocationAware) dummyInvocation;
with:
LastInvocationAware lastInvocationAware = DummyInvocationUtils.getLastInvocationAware(dummyInvocation);