Skip to content

Commit 3723a9e

Browse files
committed
Support Testcontainer JDBC URLs with Replace.NON_TEST
Update `TestDatabaseAutoConfiguration` so that Testcontainer JDBC URLs are also detected when using `Replace.NON_TEST`. Closes gh-35253
1 parent af34690 commit 3723a9e

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.jdbc;
18+
19+
import javax.sql.DataSource;
20+
21+
import com.zaxxer.hikari.HikariDataSource;
22+
import org.junit.jupiter.api.Test;
23+
import org.testcontainers.junit.jupiter.Testcontainers;
24+
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
27+
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
28+
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
29+
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
30+
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabaseTestcontainersJdbcUrlIntegrationTests.InitializeDatasourceUrl;
31+
import org.springframework.boot.test.context.SpringBootTest;
32+
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
33+
import org.springframework.boot.testsupport.container.TestImage;
34+
import org.springframework.context.ApplicationContextInitializer;
35+
import org.springframework.context.ConfigurableApplicationContext;
36+
import org.springframework.context.annotation.Configuration;
37+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
38+
import org.springframework.test.context.ContextConfiguration;
39+
import org.springframework.test.context.support.TestPropertySourceUtils;
40+
41+
import static org.assertj.core.api.Assertions.assertThat;
42+
43+
/**
44+
* Integration test for {@link AutoConfigureTestDatabase} with Testcontainers and a
45+
* {@link ServiceConnection @ServiceConnection}.
46+
*
47+
* @author Phillip Webb
48+
*/
49+
@SpringBootTest
50+
@ContextConfiguration(initializers = InitializeDatasourceUrl.class)
51+
@AutoConfigureTestDatabase(replace = Replace.NON_TEST)
52+
@Testcontainers(disabledWithoutDocker = true)
53+
@OverrideAutoConfiguration(enabled = false)
54+
class AutoConfigureTestDatabaseTestcontainersJdbcUrlIntegrationTests {
55+
56+
@Autowired
57+
private DataSource dataSource;
58+
59+
@Test
60+
void dataSourceIsNotReplaced() {
61+
assertThat(this.dataSource).isInstanceOf(HikariDataSource.class).isNotInstanceOf(EmbeddedDatabase.class);
62+
}
63+
64+
@Configuration
65+
@ImportAutoConfiguration(DataSourceAutoConfiguration.class)
66+
static class Config {
67+
68+
}
69+
70+
static class InitializeDatasourceUrl implements ApplicationContextInitializer<ConfigurableApplicationContext> {
71+
72+
@Override
73+
public void initialize(ConfigurableApplicationContext applicationContext) {
74+
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext,
75+
"spring.datasource.url=jdbc:tc:postgis:" + TestImage.POSTGRESQL.getTag() + ":///");
76+
}
77+
78+
}
79+
80+
}

spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/AutoConfigureTestDatabase.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ enum Replace {
8181
* created using Docker Compose)</li>
8282
* <li>Any connection configured using a {@code spring.datasource.url} backed by a
8383
* {@link DynamicPropertySource @DynamicPropertySource}</li>
84+
* <li>Any connection configured using a {@code spring.datasource.url} with the
85+
* Testcontainers JDBC syntax</li>
8486
* </ul>
8587
* @since 3.4.0
8688
*/

spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfiguration.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ static class EmbeddedDataSourceBeanFactoryPostProcessor implements BeanDefinitio
107107
private static final ConfigurationPropertyName DATASOURCE_URL_PROPERTY = ConfigurationPropertyName
108108
.of("spring.datasource.url");
109109

110+
private static final Bindable<String> BINDABLE_STRING = Bindable.of(String.class);
111+
110112
private static final String DYNAMIC_VALUES_PROPERTY_SOURCE_CLASS = "org.springframework.test.context.support.DynamicValuesPropertySource";
111113

112114
private static final Log logger = LogFactory.getLog(EmbeddedDataSourceBeanFactoryPostProcessor.class);
@@ -190,7 +192,7 @@ private boolean isAutoConfigured(BeanDefinitionHolder holder) {
190192
}
191193

192194
private boolean isConnectingToTestDatabase(ConfigurableListableBeanFactory beanFactory) {
193-
return isUsingTestServiceConnection(beanFactory) || isUsingDynamicPropertySournce();
195+
return isUsingTestServiceConnection(beanFactory) || isUsingTestDatasourceUrl();
194196
}
195197

196198
private boolean isUsingTestServiceConnection(ConfigurableListableBeanFactory beanFactory) {
@@ -208,11 +210,16 @@ private boolean isUsingTestServiceConnection(ConfigurableListableBeanFactory bea
208210
return false;
209211
}
210212

211-
private boolean isUsingDynamicPropertySournce() {
213+
private boolean isUsingTestDatasourceUrl() {
212214
List<ConfigurationProperty> bound = new ArrayList<>();
213215
Binder.get(this.environment, new BoundPropertiesTrackingBindHandler(bound::add))
214-
.bind(DATASOURCE_URL_PROPERTY, Bindable.of(String.class));
215-
return (!bound.isEmpty()) ? isBoundToDynamicValuesPropertySource(bound.get(0)) : false;
216+
.bind(DATASOURCE_URL_PROPERTY, BINDABLE_STRING);
217+
return (!bound.isEmpty()) ? isUsingTestDatasourceUrl(bound.get(0)) : false;
218+
}
219+
220+
private boolean isUsingTestDatasourceUrl(ConfigurationProperty configurationProperty) {
221+
return isBoundToDynamicValuesPropertySource(configurationProperty)
222+
|| isTestcontainersUrl(configurationProperty);
216223
}
217224

218225
private boolean isBoundToDynamicValuesPropertySource(ConfigurationProperty configurationProperty) {
@@ -227,6 +234,11 @@ private boolean isDynamicValuesPropertySource(PropertySource<?> propertySource)
227234
&& DYNAMIC_VALUES_PROPERTY_SOURCE_CLASS.equals(propertySource.getClass().getName());
228235
}
229236

237+
private boolean isTestcontainersUrl(ConfigurationProperty configurationProperty) {
238+
Object value = configurationProperty.getValue();
239+
return (value != null) && value.toString().startsWith("jdbc:tc:");
240+
}
241+
230242
}
231243

232244
static class EmbeddedDataSourceFactoryBean implements FactoryBean<DataSource>, EnvironmentAware, InitializingBean {

spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ private <C extends Container<?>> C createContainer(Class<C> containerClass) {
343343
}
344344
}
345345

346+
public String getTag() {
347+
return this.tag;
348+
}
349+
346350
@Override
347351
public String toString() {
348352
return (this.tag != null) ? this.name + ":" + this.tag : this.name;

0 commit comments

Comments
 (0)