From f210d83062422af46bb91c256b45e12e30f6dcf1 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 24 Apr 2024 14:37:59 -0500 Subject: [PATCH] Don't reuse Testcontainers containers if reuse is globally disabled Fixes gh-39609 --- ...tcontainersLifecycleBeanPostProcessor.java | 7 +++- ...cleApplicationContextInitializerTests.java | 40 +++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) 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 9a5ec1d10af..42fbc68e7a2 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory; import org.testcontainers.containers.ContainerState; import org.testcontainers.containers.GenericContainer; import org.testcontainers.lifecycle.Startable; +import org.testcontainers.utility.TestcontainersConfiguration; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; @@ -49,6 +50,7 @@ import org.springframework.core.log.LogMessage; * * @author Phillip Webb * @author Stephane Nicoll + * @author Scott Frederick * @see TestcontainersLifecycleApplicationContextInitializer */ @Order(Ordered.LOWEST_PRECEDENCE) @@ -124,7 +126,8 @@ class TestcontainersLifecycleBeanPostProcessor implements DestructionAwareBeanPo } private boolean isReusedContainer(Object bean) { - return (bean instanceof GenericContainer container) && container.isShouldBeReused(); + return (bean instanceof GenericContainer container) && container.isShouldBeReused() + && TestcontainersConfiguration.getInstance().environmentSupportsReuse(); } } 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 ee27dae34f7..3c89be28e94 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,11 @@ package org.springframework.boot.testcontainers.lifecycle; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; import org.testcontainers.lifecycle.Startable; +import org.testcontainers.utility.TestcontainersConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -38,9 +40,15 @@ import static org.mockito.Mockito.times; * * @author Stephane Nicoll * @author Phillip Webb + * @author Scott Frederick */ class TestcontainersLifecycleApplicationContextInitializerTests { + @BeforeEach + void setUp() { + TestcontainersConfiguration.getInstance().updateUserConfig("testcontainers.reuse.enable", "false"); + } + @Test void whenStartableBeanInvokesStartOnRefresh() { Startable container = mock(Startable.class); @@ -62,7 +70,8 @@ class TestcontainersLifecycleApplicationContextInitializerTests { } @Test - void whenReusableContainerBeanInvokesStartButNotClose() { + void whenReusableContainerAndReuseEnabledBeanInvokesStartButNotClose() { + TestcontainersConfiguration.getInstance().updateUserConfig("testcontainers.reuse.enable", "true"); GenericContainer container = mock(GenericContainer.class); given(container.isShouldBeReused()).willReturn(true); AnnotationConfigApplicationContext applicationContext = createApplicationContext(container); @@ -74,7 +83,20 @@ class TestcontainersLifecycleApplicationContextInitializerTests { } @Test - void whenReusableContainerBeanFromConfigurationInvokesStartButNotClose() { + void whenReusableContainerButReuseNotEnabledBeanInvokesStartAndClose() { + GenericContainer container = mock(GenericContainer.class); + given(container.isShouldBeReused()).willReturn(true); + AnnotationConfigApplicationContext applicationContext = createApplicationContext(container); + then(container).shouldHaveNoInteractions(); + applicationContext.refresh(); + then(container).should().start(); + applicationContext.close(); + then(container).should(times(1)).close(); + } + + @Test + void whenReusableContainerAndReuseEnabledBeanFromConfigurationInvokesStartButNotClose() { + TestcontainersConfiguration.getInstance().updateUserConfig("testcontainers.reuse.enable", "true"); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); new TestcontainersLifecycleApplicationContextInitializer().initialize(applicationContext); applicationContext.register(ReusableContainerConfiguration.class); @@ -85,6 +107,18 @@ class TestcontainersLifecycleApplicationContextInitializerTests { then(container).should(never()).close(); } + @Test + void whenReusableContainerButReuseNotEnabledBeanFromConfigurationInvokesStartAndClose() { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + new TestcontainersLifecycleApplicationContextInitializer().initialize(applicationContext); + applicationContext.register(ReusableContainerConfiguration.class); + applicationContext.refresh(); + GenericContainer container = applicationContext.getBean(GenericContainer.class); + then(container).should().start(); + applicationContext.close(); + then(container).should(times(1)).close(); + } + @Test void doesNotInitializeSameContextMoreThanOnce() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();