From e7e5ed1508dd86690da5f26b254c29f0a252ec35 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Aug 2024 18:55:07 +0100 Subject: [PATCH] Don't initialize containers during AOT processing Fixes gh-41838 --- ...tcontainersLifecycleBeanPostProcessor.java | 6 +++- ...cleApplicationContextInitializerTests.java | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanPostProcessor.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanPostProcessor.java index e870be4cdb..26a8cc9187 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanPostProcessor.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanPostProcessor.java @@ -85,7 +85,7 @@ class TestcontainersLifecycleBeanPostProcessor @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (this.beanFactory.isConfigurationFrozen()) { + if (this.beanFactory.isConfigurationFrozen() && !isAotProcessingInProgress()) { initializeContainers(); } if (bean instanceof Startable startableBean) { @@ -100,6 +100,10 @@ class TestcontainersLifecycleBeanPostProcessor return bean; } + private boolean isAotProcessingInProgress() { + return Boolean.getBoolean("spring.aot.processing"); + } + private void initializeStartables(Startable startableBean, String startableBeanName) { logger.trace(LogMessage.format("Initializing startables")); List beanNames = new ArrayList<>(getBeanNames(Startable.class)); diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleApplicationContextInitializerTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleApplicationContextInitializerTests.java index 68b5c46c41..9d9da72efc 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleApplicationContextInitializerTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleApplicationContextInitializerTests.java @@ -24,6 +24,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.lifecycle.Startable; import org.testcontainers.utility.TestcontainersConfiguration; +import org.springframework.aot.hint.RuntimeHints; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.AbstractBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -143,6 +144,17 @@ class TestcontainersLifecycleApplicationContextInitializerTests { applicationContext.refresh(); } + @Test + void doesNotStartContainersWhenAotProcessingIsInProgress() { + GenericContainer container = mock(GenericContainer.class); + AnnotationConfigApplicationContext applicationContext = createApplicationContext(container); + then(container).shouldHaveNoInteractions(); + withSystemProperty("spring.aot.processing", "true", + () -> applicationContext.refreshForAotProcessing(new RuntimeHints())); + then(container).shouldHaveNoInteractions(); + applicationContext.close(); + } + @Test void setupStartupBasedOnEnvironmentProperty() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); @@ -159,6 +171,22 @@ class TestcontainersLifecycleApplicationContextInitializerTests { assertThat(beanPostProcessor).extracting("startup").isEqualTo(TestcontainersStartup.PARALLEL); } + private void withSystemProperty(String name, String value, Runnable action) { + String previousValue = System.getProperty(name); + System.setProperty(name, value); + try { + action.run(); + } + finally { + if (previousValue == null) { + System.clearProperty(name); + } + else { + System.setProperty(name, previousValue); + } + } + } + private AnnotationConfigApplicationContext createApplicationContext(Startable container) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); new TestcontainersLifecycleApplicationContextInitializer().initialize(applicationContext); @@ -166,6 +194,13 @@ class TestcontainersLifecycleApplicationContextInitializerTests { return applicationContext; } + private AnnotationConfigApplicationContext createApplicationContext(GenericContainer container) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + new TestcontainersLifecycleApplicationContextInitializer().initialize(applicationContext); + applicationContext.registerBean("container", GenericContainer.class, () -> container); + return applicationContext; + } + @Configuration static class ReusableContainerConfiguration {