Hi, we're facing an issue with Spring Boot 3.2.2. Currently we use 3.1.8 together with "id 'org.graalvm.buildtools.native' version '0.9.28'" and we have an unit test that contains a MockBean of JwtDecoder.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringBootComponentTest {
@MockBean
JwtDecoder jwtDecoder;
// etc...
}
With 3.1.8 everything works fine. But when we change to 3.2.2 we get the following error during test build (e.g. gradle check):
> Task :processTestAot
12:35:39.881 [main] INFO org.springframework.test.context.aot.TestClassScanner -- Scanning for Spring test classes in all packages in classpath roots [/home/websocket/build/classes/java/test, /home/websocket/build/resources/test]
12:35:40.219 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.neoalto.websocket.DeserializeMessageFromServicesJsonTest]: DeserializeMessageFromServicesJsonTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
12:35:40.332 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.neoalto.websocket.WebsocketApplication for test class com.neoalto.websocket.DeserializeMessageFromServicesJsonTest
12:35:40.406 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.neoalto.websocket.WebsocketApplicationTest]: WebsocketApplicationTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
12:35:40.410 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.neoalto.websocket.WebsocketApplication for test class com.neoalto.websocket.WebsocketApplicationTest
2024-02-02 12:35:40.749 INFO [ main] w.DeserializeMessageFromServicesJsonTest : Starting DeserializeMessageFromServicesJsonTest using Java 17.0.1 with PID 277270 (/home/websocket/build/classes/java/test started by peter in /home/websocket)
2024-02-02 12:35:40.750 DEBUG [ main] w.DeserializeMessageFromServicesJsonTest : Running with Spring Boot v3.2.2, Spring v6.1.3
2024-02-02 12:35:40.751 INFO [ main] w.DeserializeMessageFromServicesJsonTest : The following 1 profile is active: "integration"
2024-02-02 12:35:41.353 DEBUG [ main] c.n.websocket.WebsocketApplication : Setting defaults..
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
Exception in thread "main" org.springframework.test.context.aot.TestContextAotException: Failed to generate AOT artifacts for test classes [com.neoalto.websocket.DeserializeMessageFromServicesJsonTest, com.neoalto.websocket.WebsocketApplicationTest]
at org.springframework.test.context.aot.TestContextAotGenerator.lambda$processAheadOfTime$5(TestContextAotGenerator.java:286)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.springframework.util.MultiValueMapAdapter.forEach(MultiValueMapAdapter.java:179)
at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:244)
at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:205)
at org.springframework.test.context.aot.TestAotProcessor.performAotProcessing(TestAotProcessor.java:91)
at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:72)
at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:39)
at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
at org.springframework.boot.test.context.SpringBootTestAotProcessor.main(SpringBootTestAotProcessor.java:63)
Caused by: org.springframework.test.context.aot.TestContextAotException: Failed to process test class [com.neoalto.websocket.DeserializeMessageFromServicesJsonTest] for AOT
at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:323)
at org.springframework.test.context.aot.TestContextAotGenerator.lambda$processAheadOfTime$5(TestContextAotGenerator.java:277)
... 9 more
Caused by: org.springframework.aot.generate.ValueCodeGenerationException: Failed to generate code for '[[MockDefinition@374c3975 name = '', typeToMock = org.springframework.security.oauth2.jwt.JwtDecoder, extraInterfaces = set[[empty]], answer = RETURNS_DEFAULTS, serializable = false, reset = AFTER], [SpyDefinition@43c39321 name = '', typeToSpy = com.neoalto.websocket.websocket_sessions.LogHelper, reset = AFTER]]' with type class java.util.LinkedHashSet
at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:116)
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:269)
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$addConstructorArgumentValues$3(BeanDefinitionPropertiesCodeGenerator.java:191)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at java.base/java.util.Collections$UnmodifiableMap.forEach(Collections.java:1553)
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addConstructorArgumentValues(BeanDefinitionPropertiesCodeGenerator.java:188)
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:134)
at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:181)
at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:81)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$generateBeanDefinitionMethod$3(BeanDefinitionMethodGenerator.java:176)
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:54)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:112)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:89)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:169)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:89)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$generateRegisterBeanDefinitionsMethod$2(BeanRegistrationsAotContribution.java:90)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterBeanDefinitionsMethod(BeanRegistrationsAotContribution.java:88)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$applyTo$1(BeanRegistrationsAotContribution.java:73)
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:54)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:112)
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:89)
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.applyTo(BeanRegistrationsAotContribution.java:72)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78)
at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:319)
... 10 more
Caused by: org.springframework.aot.generate.ValueCodeGenerationException: Failed to generate code for '[MockDefinition@374c3975 name = '', typeToMock = org.springframework.security.oauth2.jwt.JwtDecoder, extraInterfaces = set[[empty]], answer = RETURNS_DEFAULTS, serializable = false, reset = AFTER]' with type class org.springframework.boot.test.mock.mockito.MockDefinition
at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:116)
at org.springframework.aot.generate.ValueCodeGeneratorDelegates$CollectionDelegate.generateCollectionOf(ValueCodeGeneratorDelegates.java:119)
at org.springframework.aot.generate.ValueCodeGeneratorDelegates$SetDelegate.generateCollectionCode(ValueCodeGeneratorDelegates.java:401)
at org.springframework.aot.generate.ValueCodeGeneratorDelegates$SetDelegate.generateCollectionCode(ValueCodeGeneratorDelegates.java:391)
at org.springframework.aot.generate.ValueCodeGeneratorDelegates$CollectionDelegate.generateCode(ValueCodeGeneratorDelegates.java:103)
at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:108)
... 37 more
Caused by: org.springframework.aot.generate.UnsupportedTypeValueCodeGenerationException: Code generation does not support org.springframework.boot.test.mock.mockito.MockDefinition
at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:113)
... 42 more
> Task :processTestAot FAILED
FAILURE: Build failed with an exception.
This looks like a bug to me. Could you please have a look? Thanks in advance!
Comment From: wilkinsona
@MockBean isn't supported with AOT-processed tests. In Spring Boot 3.1, this resulted in a silent failure and the test that used it being skipped. In 3.2, we've upgraded to Spring Framework 6.1 whose test framework now fails fast in such a situation. Please see https://github.com/spring-projects/spring-boot/issues/32195 for further details. You can use the new @DisabledInAotMode to opt back into an equivalent of the old behavior.
Comment From: pbilstein
@wilkinsona Interesting! Thanks for the quick response.