diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java index e13959825c8..3d1be7b897a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java @@ -34,9 +34,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.init.DatabasePopulator; @@ -103,6 +105,7 @@ public class BatchAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnBean(DataSource.class) @ConditionalOnClass(DatabasePopulator.class) + @Conditional(OnBatchDatasourceInitializationCondition.class) static class DataSourceInitializerConfiguration { @Bean @@ -116,4 +119,12 @@ public class BatchAutoConfiguration { } + static class OnBatchDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnBatchDatasourceInitializationCondition() { + super("Batch", "spring.batch.jdbc.initialize-schema", "spring.batch.initialize-schema"); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java index 10ee727e13a..33e59604f98 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java @@ -36,6 +36,7 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; @@ -233,6 +234,7 @@ public class IntegrationAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(JdbcMessageStore.class) @ConditionalOnSingleCandidate(DataSource.class) + @Conditional(OnIntegrationDatasourceInitializationCondition.class) protected static class IntegrationJdbcConfiguration { @Bean @@ -342,4 +344,12 @@ public class IntegrationAutoConfiguration { } + static class OnIntegrationDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnIntegrationDatasourceInitializationCondition() { + super("Integration", "spring.integration.jdbc.initialize-schema"); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java index 1c7b5df2e3e..48725001efd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java @@ -37,10 +37,12 @@ import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; @@ -134,6 +136,7 @@ public class QuartzAutoConfiguration { @SuppressWarnings("deprecation") @ConditionalOnMissingBean({ QuartzDataSourceScriptDatabaseInitializer.class, QuartzDataSourceInitializer.class }) + @Conditional(OnQuartzDatasourceInitializationCondition.class) public QuartzDataSourceScriptDatabaseInitializer quartzDataSourceScriptDatabaseInitializer( DataSource dataSource, @QuartzDataSource ObjectProvider quartzDataSource, QuartzProperties properties) { @@ -141,6 +144,14 @@ public class QuartzAutoConfiguration { return new QuartzDataSourceScriptDatabaseInitializer(dataSourceToUse, properties); } + static class OnQuartzDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnQuartzDatasourceInitializationCondition() { + super("Quartz", "spring.quartz.jdbc.initialize-schema"); + } + + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java index 65fa4d7dbe5..397a89f60f2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; @@ -58,6 +59,7 @@ class JdbcSessionConfiguration { @SuppressWarnings("deprecation") @ConditionalOnMissingBean({ JdbcSessionDataSourceScriptDatabaseInitializer.class, JdbcSessionDataSourceInitializer.class }) + @Conditional(OnJdbcSessionDatasourceInitializationCondition.class) JdbcSessionDataSourceScriptDatabaseInitializer jdbcSessionDataSourceScriptDatabaseInitializer( @SpringSessionDataSource ObjectProvider sessionDataSource, ObjectProvider dataSource, JdbcSessionProperties properties) { @@ -84,4 +86,12 @@ class JdbcSessionConfiguration { } + static class OnJdbcSessionDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnJdbcSessionDatasourceInitializationCondition() { + super("Jdbc Session", "spring.session.jdbc.initialize-schema"); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationCondition.java new file mode 100644 index 00000000000..f986b0bdc1c --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationCondition.java @@ -0,0 +1,90 @@ +/* + * Copyright 2012-2021 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.autoconfigure.sql.init; + +import java.util.Locale; + +import org.springframework.boot.autoconfigure.condition.ConditionMessage; +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.boot.sql.init.DatabaseInitializationMode; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.Environment; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.util.StringUtils; + +/** + * Condition that checks if the database initialization of a particular component should + * be considered. + * + * @author Stephane Nicoll + * @since 2.6.2 + * @see DatabaseInitializationMode + */ +public class OnDatabaseInitializationCondition extends SpringBootCondition { + + private final String name; + + private final String[] propertyNames; + + /** + * Create a new instance with the name of the component and the property names to + * check, in order. If a property is set, its value is used to determine the outcome + * and remaining properties are not tested. + * @param name the name of the component + * @param propertyNames the properties to check (in order) + */ + public OnDatabaseInitializationCondition(String name, String... propertyNames) { + this.name = name; + this.propertyNames = propertyNames; + } + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + Environment environment = context.getEnvironment(); + String propertyName = getConfiguredProperty(environment); + DatabaseInitializationMode mode = getDatabaseInitializationMode(environment, propertyName); + boolean match = match(mode); + String messagePrefix = (propertyName != null) ? propertyName : "default value"; + return new ConditionOutcome(match, ConditionMessage.forCondition(this.name + "Database Initialization") + .because(messagePrefix + " is " + mode)); + } + + private boolean match(DatabaseInitializationMode mode) { + return !mode.equals(DatabaseInitializationMode.NEVER); + } + + private DatabaseInitializationMode getDatabaseInitializationMode(Environment environment, String propertyName) { + if (StringUtils.hasText(propertyName)) { + String candidate = environment.getProperty(propertyName, "embedded").toUpperCase(Locale.ENGLISH); + if (StringUtils.hasText(candidate)) { + return DatabaseInitializationMode.valueOf(candidate); + } + } + return DatabaseInitializationMode.EMBEDDED; + } + + private String getConfiguredProperty(Environment environment) { + for (String propertyName : this.propertyNames) { + if (environment.containsProperty(propertyName)) { + return propertyName; + } + } + return null; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index 4769602b5fa..d51274d2707 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -205,6 +205,7 @@ class BatchAutoConfigurationTests { assertThat(context).hasSingleBean(JobLauncher.class); assertThat(context.getBean(BatchProperties.class).getJdbc().getInitializeSchema()) .isEqualTo(DatabaseInitializationMode.NEVER); + assertThat(context).doesNotHaveBean(BatchDataSourceScriptDatabaseInitializer.class); assertThatExceptionOfType(BadSqlGrammarException.class) .isThrownBy(() -> new JdbcTemplate(context.getBean(DataSource.class)) .queryForList("select * from BATCH_JOB_EXECUTION")); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java index 4f66bd16454..9c963c1dd80 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java @@ -210,6 +210,7 @@ class IntegrationAutoConfigurationTests { .withPropertyValues("spring.datasource.generate-unique-name=true", "spring.integration.jdbc.initialize-schema=never") .run((context) -> { + assertThat(context).doesNotHaveBean(IntegrationDataSourceScriptDatabaseInitializer.class); IntegrationProperties properties = context.getBean(IntegrationProperties.class); assertThat(properties.getJdbc().getInitializeSchema()).isEqualTo(DatabaseInitializationMode.NEVER); JdbcOperations jdbc = context.getBean(JdbcOperations.class); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java index c64adebd80b..e0f891b3d40 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java @@ -114,7 +114,8 @@ class QuartzAutoConfigurationTests { this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class) .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class)) - .withPropertyValues("spring.quartz.job-store-type=jdbc").run(assertDataSourceJobStore("dataSource")); + .withPropertyValues("spring.quartz.job-store-type=jdbc") + .run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("dataSource")); } @Test @@ -134,14 +135,15 @@ class QuartzAutoConfigurationTests { void withDataSourceNoTransactionManager() { this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class) .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) - .withPropertyValues("spring.quartz.job-store-type=jdbc").run(assertDataSourceJobStore("dataSource")); + .withPropertyValues("spring.quartz.job-store-type=jdbc") + .run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("dataSource")); } @Test void dataSourceWithQuartzDataSourceQualifierUsedWhenMultiplePresent() { this.contextRunner.withUserConfiguration(QuartzJobsConfiguration.class, MultipleDataSourceConfiguration.class) .withPropertyValues("spring.quartz.job-store-type=jdbc") - .run(assertDataSourceJobStore("quartzDataSource")); + .run(assertDataSourceInitializedByDataSourceDatabaseScriptInitializer("quartzDataSource")); } @Test @@ -155,23 +157,6 @@ class QuartzAutoConfigurationTests { }); } - private ContextConsumer assertDataSourceJobStore(String dataSourceName) { - return (context) -> { - assertThat(context).hasSingleBean(Scheduler.class); - Scheduler scheduler = context.getBean(Scheduler.class); - assertThat(scheduler.getMetaData().getJobStoreClass()).isAssignableFrom(LocalDataSourceJobStore.class); - JdbcTemplate jdbcTemplate = new JdbcTemplate(context.getBean(dataSourceName, DataSource.class)); - assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM QRTZ_JOB_DETAILS", Integer.class)) - .isEqualTo(2); - assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM QRTZ_SIMPLE_TRIGGERS", Integer.class)) - .isEqualTo(0); - assertThat(context).hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class); - QuartzDataSourceScriptDatabaseInitializer initializer = context - .getBean(QuartzDataSourceScriptDatabaseInitializer.class); - assertThat(initializer).hasFieldOrPropertyWithValue("dataSource", context.getBean(dataSourceName)); - }; - } - @Test void withTaskExecutor() { this.contextRunner.withUserConfiguration(MockExecutorConfiguration.class) @@ -277,7 +262,8 @@ class QuartzAutoConfigurationTests { DataSourceTransactionManagerAutoConfiguration.class, LiquibaseAutoConfiguration.class)) .withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never", "spring.liquibase.change-log=classpath:org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml") - .run(assertDataSourceJobStore("dataSource")); + .run(assertDataSourceInitialized("dataSource").andThen((context) -> assertThat(context) + .doesNotHaveBean(QuartzDataSourceScriptDatabaseInitializer.class))); } @Test @@ -292,7 +278,8 @@ class QuartzAutoConfigurationTests { .withPropertyValues("spring.quartz.job-store-type=jdbc", "spring.quartz.jdbc.initialize-schema=never", "spring.flyway.locations=filesystem:" + flywayLocation, "spring.flyway.baseline-on-migrate=true") - .run(assertDataSourceJobStore("dataSource")); + .run(assertDataSourceInitialized("dataSource").andThen((context) -> assertThat(context) + .doesNotHaveBean(QuartzDataSourceScriptDatabaseInitializer.class))); } @Test @@ -352,6 +339,29 @@ class QuartzAutoConfigurationTests { .hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class).hasBean("customInitializer")); } + private ContextConsumer assertDataSourceInitialized(String dataSourceName) { + return (context) -> { + assertThat(context).hasSingleBean(Scheduler.class); + Scheduler scheduler = context.getBean(Scheduler.class); + assertThat(scheduler.getMetaData().getJobStoreClass()).isAssignableFrom(LocalDataSourceJobStore.class); + JdbcTemplate jdbcTemplate = new JdbcTemplate(context.getBean(dataSourceName, DataSource.class)); + assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM QRTZ_JOB_DETAILS", Integer.class)) + .isEqualTo(2); + assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM QRTZ_SIMPLE_TRIGGERS", Integer.class)) + .isEqualTo(0); + }; + } + + private ContextConsumer assertDataSourceInitializedByDataSourceDatabaseScriptInitializer( + String dataSourceName) { + return assertDataSourceInitialized(dataSourceName).andThen((context) -> { + assertThat(context).hasSingleBean(QuartzDataSourceScriptDatabaseInitializer.class); + QuartzDataSourceScriptDatabaseInitializer initializer = context + .getBean(QuartzDataSourceScriptDatabaseInitializer.class); + assertThat(initializer).hasFieldOrPropertyWithValue("dataSource", context.getBean(dataSourceName)); + }); + } + private ContextConsumer assertSchedulerName(String schedulerName) { return (context) -> { assertThat(context).hasSingleBean(SchedulerFactoryBean.class); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java index 9eecf4cd22e..069c2a782fc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java @@ -110,6 +110,7 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration this.contextRunner .withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.initialize-schema=never") .run((context) -> { + assertThat(context).doesNotHaveBean(JdbcSessionDataSourceScriptDatabaseInitializer.class); JdbcIndexedSessionRepository repository = validateSessionRepository(context, JdbcIndexedSessionRepository.class); assertThat(repository).hasFieldOrPropertyWithValue("tableName", "SPRING_SESSION"); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationConditionTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationConditionTests.java new file mode 100644 index 00000000000..8378fb2b570 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/sql/init/OnDatabaseInitializationConditionTests.java @@ -0,0 +1,110 @@ +/* + * Copyright 2012-2021 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.autoconfigure.sql.init; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link OnDatabaseInitializationCondition}. + * + * @author Stephane Nicoll + */ +class OnDatabaseInitializationConditionTests { + + @Test + void getMatchOutcomeWithPropertyNoSetMatches() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.another", "noise")), null); + assertThat(outcome.isMatch()).isTrue(); + } + + @Test + void getMatchOutcomeWithPropertySetToAlwaysMatches() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-mode=always")), null); + assertThat(outcome.isMatch()).isTrue(); + } + + @Test + void getMatchOutcomeWithPropertySetToEmbeddedMatches() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-mode=embedded")), null); + assertThat(outcome.isMatch()).isTrue(); + } + + @Test + void getMatchOutcomeWithPropertySetToNeverDoesNotMatch() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-mode=never")), null); + assertThat(outcome.isMatch()).isFalse(); + } + + @Test + void getMatchOutcomeWithPropertySetToEmptyStringIsIgnored() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-mode")), null); + assertThat(outcome.isMatch()).isTrue(); + } + + @Test + void getMatchOutcomeWithMultiplePropertiesUsesFirstSet() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode", + "test.schema-mode", "test.init-schema-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-schema-mode=embedded")), null); + assertThat(outcome.isMatch()).isTrue(); + assertThat(outcome.getMessage()).isEqualTo("TestDatabase Initialization test.init-schema-mode is EMBEDDED"); + } + + @Test + void getMatchOutcomeHasDedicatedDescription() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition + .getMatchOutcome(mockConditionContext(TestPropertyValues.of("test.init-mode=embedded")), null); + assertThat(outcome.getMessage()).isEqualTo("TestDatabase Initialization test.init-mode is EMBEDDED"); + } + + @Test + void getMatchOutcomeHasWhenPropertyIsNotSetHasDefaultDescription() { + OnDatabaseInitializationCondition condition = new OnDatabaseInitializationCondition("Test", "test.init-mode"); + ConditionOutcome outcome = condition.getMatchOutcome(mockConditionContext(TestPropertyValues.empty()), null); + assertThat(outcome.getMessage()).isEqualTo("TestDatabase Initialization default value is EMBEDDED"); + } + + private ConditionContext mockConditionContext(TestPropertyValues propertyValues) { + MockEnvironment environment = new MockEnvironment(); + propertyValues.applyTo(environment); + ConditionContext conditionContext = mock(ConditionContext.class); + given(conditionContext.getEnvironment()).willReturn(environment); + return conditionContext; + } + +}