mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Migrate AOT tests to use GeneratedClasses and refine/polish AOT APIs
Migrate all AOT tests to make use of `GeneratedClasses` rather than directly generating Java files. This commit also refines and polishes AOT APIs to being greater consistency. Specifically: - The `MethodGenerator` interface has been removed in favor of working directly with `GeneratedMethods`. - The visibility of several constructors and methods has been reduced to package-private. - The `using(...)` and `builder` methods have been removed in favor of setting the `Consumer` callbacks directly as constructor arguments. - Variable names for builders are now named `type` or `method` depending on what they're building. Closes gh-28831
This commit is contained in:
+30
-37
@@ -39,10 +39,8 @@ import org.springframework.context.testfixture.context.generator.annotation.Impo
|
||||
import org.springframework.context.testfixture.context.generator.annotation.ImportConfiguration;
|
||||
import org.springframework.core.testfixture.aot.generate.TestGenerationContext;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.JavaFile;
|
||||
import org.springframework.javapoet.MethodSpec;
|
||||
import org.springframework.javapoet.ParameterizedTypeName;
|
||||
import org.springframework.javapoet.TypeSpec;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -56,21 +54,26 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
*/
|
||||
class ConfigurationClassPostProcessorAotContributionTests {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
private final InMemoryGeneratedFiles generatedFiles;
|
||||
|
||||
private InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
|
||||
private final DefaultGenerationContext generationContext;
|
||||
|
||||
private DefaultGenerationContext generationContext = new TestGenerationContext(
|
||||
this.generatedFiles);
|
||||
private final MockBeanFactoryInitializationCode beanFactoryInitializationCode;
|
||||
|
||||
|
||||
ConfigurationClassPostProcessorAotContributionTests() {
|
||||
this.generatedFiles = new InMemoryGeneratedFiles();
|
||||
this.generationContext = new TestGenerationContext(this.generatedFiles);
|
||||
this.beanFactoryInitializationCode = new MockBeanFactoryInitializationCode(this.generationContext);
|
||||
}
|
||||
|
||||
private MockBeanFactoryInitializationCode beanFactoryInitializationCode = new MockBeanFactoryInitializationCode();
|
||||
|
||||
@Test
|
||||
void applyToWhenHasImportAwareConfigurationRegistersBeanPostProcessorWithMapEntry() {
|
||||
BeanFactoryInitializationAotContribution contribution = getContribution(
|
||||
ImportConfiguration.class);
|
||||
contribution.applyTo(this.generationContext, this.beanFactoryInitializationCode);
|
||||
testCompiledResult((initializer, compiled) -> {
|
||||
compile((initializer, compiled) -> {
|
||||
DefaultListableBeanFactory freshBeanFactory = new DefaultListableBeanFactory();
|
||||
initializer.accept(freshBeanFactory);
|
||||
ImportAwareAotBeanPostProcessor postProcessor = (ImportAwareAotBeanPostProcessor) freshBeanFactory
|
||||
@@ -89,8 +92,8 @@ class ConfigurationClassPostProcessorAotContributionTests {
|
||||
.singleElement()
|
||||
.satisfies(resourceHint -> assertThat(resourceHint.getIncludes())
|
||||
.map(ResourcePatternHint::getPattern)
|
||||
.containsOnly(
|
||||
"org/springframework/context/testfixture/context/generator/annotation/ImportConfiguration.class"));
|
||||
.containsOnly("org/springframework/context/testfixture/context/generator/annotation/"
|
||||
+ "ImportConfiguration.class"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,38 +103,28 @@ class ConfigurationClassPostProcessorAotContributionTests {
|
||||
|
||||
@Nullable
|
||||
private BeanFactoryInitializationAotContribution getContribution(Class<?> type) {
|
||||
this.beanFactory.registerBeanDefinition("configuration",
|
||||
new RootBeanDefinition(type));
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerBeanDefinition("configuration", new RootBeanDefinition(type));
|
||||
ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();
|
||||
postProcessor.postProcessBeanFactory(this.beanFactory);
|
||||
return postProcessor.processAheadOfTime(this.beanFactory);
|
||||
postProcessor.postProcessBeanFactory(beanFactory);
|
||||
return postProcessor.processAheadOfTime(beanFactory);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void testCompiledResult(
|
||||
BiConsumer<Consumer<DefaultListableBeanFactory>, Compiled> result) {
|
||||
JavaFile javaFile = createJavaFile();
|
||||
private void compile(BiConsumer<Consumer<DefaultListableBeanFactory>, Compiled> result) {
|
||||
MethodReference methodReference = this.beanFactoryInitializationCode
|
||||
.getInitializers().get(0);
|
||||
this.beanFactoryInitializationCode.getTypeBuilder().set(type -> {
|
||||
type.addModifiers(Modifier.PUBLIC);
|
||||
type.addSuperinterface(ParameterizedTypeName.get(Consumer.class, DefaultListableBeanFactory.class));
|
||||
type.addMethod(MethodSpec.methodBuilder("accept").addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(DefaultListableBeanFactory.class, "beanFactory")
|
||||
.addStatement(methodReference.toInvokeCodeBlock(CodeBlock.of("beanFactory")))
|
||||
.build());
|
||||
});
|
||||
this.generationContext.writeGeneratedContent();
|
||||
TestCompiler.forSystem().withFiles(this.generatedFiles).compile(javaFile::writeTo,
|
||||
compiled -> result.accept(compiled.getInstance(Consumer.class),
|
||||
compiled));
|
||||
}
|
||||
|
||||
private JavaFile createJavaFile() {
|
||||
MethodReference methodReference = this.beanFactoryInitializationCode.getInitializers()
|
||||
.get(0);
|
||||
TypeSpec.Builder builder = TypeSpec.classBuilder("TestConsumer");
|
||||
builder.addModifiers(Modifier.PUBLIC);
|
||||
builder.addSuperinterface(ParameterizedTypeName.get(Consumer.class,
|
||||
DefaultListableBeanFactory.class));
|
||||
builder.addMethod(MethodSpec.methodBuilder("accept").addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(DefaultListableBeanFactory.class, "beanFactory")
|
||||
.addStatement(
|
||||
methodReference.toInvokeCodeBlock(CodeBlock.of("beanFactory")))
|
||||
.build());
|
||||
this.beanFactoryInitializationCode.getMethodGenerator()
|
||||
.doWithMethodSpecs(builder::addMethod);
|
||||
return JavaFile.builder("__", builder.build()).build();
|
||||
TestCompiler.forSystem().withFiles(this.generatedFiles).compile(compiled ->
|
||||
result.accept(compiled.getInstance(Consumer.class), compiled));
|
||||
}
|
||||
|
||||
private void assertPostProcessorEntry(ImportAwareAotBeanPostProcessor postProcessor,
|
||||
|
||||
+3
-6
@@ -188,14 +188,11 @@ class ApplicationContextAotGeneratorTests {
|
||||
BiConsumer<ApplicationContextInitializer<GenericApplicationContext>, Compiled> result) {
|
||||
ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator();
|
||||
InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
|
||||
DefaultGenerationContext generationContext = new TestGenerationContext(
|
||||
generatedFiles);
|
||||
DefaultGenerationContext generationContext = new TestGenerationContext(generatedFiles);
|
||||
generator.generateApplicationContext(applicationContext, generationContext);
|
||||
generationContext.writeGeneratedContent();
|
||||
TestCompiler.forSystem().withFiles(generatedFiles)
|
||||
.compile(compiled -> result.accept(
|
||||
compiled.getInstance(ApplicationContextInitializer.class),
|
||||
compiled));
|
||||
TestCompiler.forSystem().withFiles(generatedFiles).compile(compiled ->
|
||||
result.accept(compiled.getInstance(ApplicationContextInitializer.class), compiled));
|
||||
}
|
||||
|
||||
private GenericApplicationContext toFreshApplicationContext(
|
||||
|
||||
+2
-1
@@ -25,6 +25,7 @@ import java.lang.annotation.Target;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.aot.hint.MemberCategory;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
@@ -53,7 +54,7 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
|
||||
|
||||
private final ReflectiveProcessorBeanRegistrationAotProcessor processor = new ReflectiveProcessorBeanRegistrationAotProcessor();
|
||||
|
||||
private final GenerationContext generationContext = new TestGenerationContext();
|
||||
private final GenerationContext generationContext = new TestGenerationContext(new InMemoryGeneratedFiles());
|
||||
|
||||
@Test
|
||||
void shouldIgnoreNonAnnotatedType() {
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.aot.hint.ResourceBundleHint;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
@@ -55,7 +56,7 @@ class RuntimeHintsBeanFactoryInitializationAotProcessorTests {
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.generationContext = new TestGenerationContext();
|
||||
this.generationContext = new TestGenerationContext(new InMemoryGeneratedFiles());
|
||||
this.generator = new ApplicationContextAotGenerator();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user