diff --git a/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.java b/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.java
index 3326fc7541a..fb876bee8eb 100644
--- a/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.java
+++ b/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.java
@@ -61,7 +61,7 @@ import org.springframework.util.Assert;
* @author Andy Wilkinson
* @since 1.3.3
*/
-@ConditionalOnClass(DataSource.class)
+@ConditionalOnClass({ DataSource.class, DataSourceProperties.class })
@ConditionalOnEnabledDevTools
@Conditional(DevToolsDataSourceCondition.class)
@AutoConfiguration(afterName = "org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration")
diff --git a/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfiguration.java b/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfiguration.java
index d544d5d077a..21f2000362a 100644
--- a/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfiguration.java
+++ b/module/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfiguration.java
@@ -51,7 +51,7 @@ import org.springframework.util.Assert;
* @author Phillip Webb
* @since 2.5.6
*/
-@ConditionalOnClass(ConnectionFactory.class)
+@ConditionalOnClass({ ConnectionFactory.class, R2dbcAutoConfiguration.class })
@ConditionalOnEnabledDevTools
@Conditional(DevToolsConnectionFactoryCondition.class)
@AutoConfiguration(afterName = "org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration")
diff --git a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsAutoConfigurationTests.java b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsAutoConfigurationTests.java
new file mode 100644
index 00000000000..17bac765e4e
--- /dev/null
+++ b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsAutoConfigurationTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-present 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.devtools.autoconfigure;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * Base class for tests for {@link DevToolsDataSourceAutoConfiguration}.
+ *
+ * @author Stephane Nicoll
+ */
+abstract class AbstractDevToolsAutoConfigurationTests {
+
+ /**
+ * Create an {@link AssertableApplicationContext} from the given {@code supplier}.
+ *
+ * Devtools auto-configuration backs-off when it detects JUnit in the call stack. This
+ * method initializes the context in a separate thread to ignore that particular
+ * condition.
+ * @param supplier a supplier of the context
+ * @return an assertable context
+ */
+ protected AssertableApplicationContext getContext(Supplier supplier)
+ throws Exception {
+ AtomicReference atomicReference = new AtomicReference<>();
+ Thread thread = new Thread(() -> {
+ ConfigurableApplicationContext context = supplier.get();
+ atomicReference.getAndSet(context);
+ });
+ thread.start();
+ thread.join();
+ return AssertableApplicationContext.get(atomicReference::get);
+ }
+
+}
diff --git a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java
index 46726c8fb6b..81377ae334a 100644
--- a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java
+++ b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java
@@ -20,8 +20,6 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
import javax.sql.DataSource;
@@ -38,7 +36,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.willReturn;
@@ -51,7 +48,7 @@ import static org.mockito.Mockito.spy;
*
* @author Andy Wilkinson
*/
-abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
+abstract class AbstractDevToolsDataSourceAutoConfigurationTests extends AbstractDevToolsAutoConfigurationTests {
@Test
void singleManuallyConfiguredDataSourceIsNotClosed() throws Exception {
@@ -94,20 +91,6 @@ abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
return statement;
}
- protected ConfigurableApplicationContext getContext(Supplier supplier)
- throws Exception {
- AtomicReference atomicReference = new AtomicReference<>();
- Thread thread = new Thread(() -> {
- ConfigurableApplicationContext context = supplier.get();
- atomicReference.getAndSet(context);
- });
- thread.start();
- thread.join();
- ConfigurableApplicationContext context = atomicReference.get();
- assertThat(context).isNotNull();
- return context;
- }
-
protected final ConfigurableApplicationContext createContext(Class>... classes) {
return createContext(null, classes);
}
diff --git a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfigurationWithoutSpringBootJdbcTests.java b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfigurationWithoutSpringBootJdbcTests.java
new file mode 100644
index 00000000000..6dc17635ff6
--- /dev/null
+++ b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfigurationWithoutSpringBootJdbcTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-present 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.devtools.autoconfigure;
+
+import javax.sql.DataSource;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration.NonEmbeddedInMemoryDatabaseShutdownExecutor;
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link DevToolsDataSourceAutoConfiguration} when {@code spring-boot-jdbc} is
+ * not on the classpath.
+ *
+ * @author Kosuke Yanagihara
+ */
+@ClassPathExclusions(packages = "org.springframework.boot.jdbc.autoconfigure")
+class DevToolsDataSourceAutoConfigurationWithoutSpringBootJdbcTests extends AbstractDevToolsAutoConfigurationTests {
+
+ @Test
+ void backsOffWithSingleManuallyConfiguredDataSource() throws Exception {
+ try (AssertableApplicationContext context = getContext(
+ () -> new AnnotationConfigApplicationContext(SingleDataSourceConfiguration.class))) {
+ assertThat(context).hasSingleBean(DataSource.class)
+ .doesNotHaveBean(NonEmbeddedInMemoryDatabaseShutdownExecutor.class);
+ }
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @ImportAutoConfiguration(DevToolsDataSourceAutoConfiguration.class)
+ static class SingleDataSourceConfiguration {
+
+ @Bean
+ DataSource dataSource() {
+ return mock(DataSource.class);
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfigurationTests.java b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfigurationTests.java
index 61c0983f006..01f4ec8f797 100644
--- a/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfigurationTests.java
+++ b/module/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsR2dbcAutoConfigurationTests.java
@@ -30,9 +30,12 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.devtools.autoconfigure.DevToolsR2dbcAutoConfiguration.InMemoryR2dbcDatabaseShutdownExecutor;
import org.springframework.boot.devtools.autoconfigure.DevToolsR2dbcAutoConfiguration.R2dbcDatabaseShutdownEvent;
import org.springframework.boot.r2dbc.SimpleConnectionFactoryProvider.SimpleTestConnectionFactory;
import org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration;
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.context.ApplicationListener;
@@ -40,6 +43,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
import org.springframework.util.ObjectUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -49,7 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Phillip Webb
*/
-class DevToolsR2dbcAutoConfigurationTests {
+class DevToolsR2dbcAutoConfigurationTests extends AbstractDevToolsAutoConfigurationTests {
static List shutdowns = Collections.synchronizedList(new ArrayList<>());
@@ -166,6 +170,28 @@ class DevToolsR2dbcAutoConfigurationTests {
}
+ @Nested
+ @ClassPathExclusions(packages = "org.springframework.boot.r2dbc.autoconfigure")
+ class WithoutSpringBootR2dbc {
+
+ @Test
+ void backsOffWithSingleManuallyConfiguredConnectionFactory() throws Exception {
+ try (AssertableApplicationContext context = getContext(() -> new AnnotationConfigApplicationContext(
+ SingleConnectionFactoryWithDevToolsConfiguration.class))) {
+ assertThat(context).hasSingleBean(ConnectionFactory.class)
+ .doesNotHaveBean(InMemoryR2dbcDatabaseShutdownExecutor.class);
+ }
+ }
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @Import(SingleConnectionFactoryConfiguration.class)
+ @ImportAutoConfiguration(DevToolsR2dbcAutoConfiguration.class)
+ static class SingleConnectionFactoryWithDevToolsConfiguration {
+
+ }
+
@Configuration(proxyBeanMethods = false)
static class SingleConnectionFactoryConfiguration {