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.