/*
* Copyright 2012-2017 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
*
* http://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.condition;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage;
/**
* Tests for {@link ConditionalOnProperty}.
*
* @author Maciej Walkowiak
* @author Stephane Nicoll
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ConditionalOnPropertyTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private ConfigurableApplicationContext context;
private ConfigurableEnvironment environment = new StandardEnvironment();
@After
public void tearDown() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void allPropertiesAreDefined() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=value1",
"property2=value2");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void notAllPropertiesAreDefined() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=value1");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void propertyValueEqualsFalse() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=false",
"property2=value2");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void propertyValueEqualsFALSE() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=FALSE",
"property2=value2");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void relaxedName() {
load(RelaxedPropertiesRequiredConfiguration.class,
"spring.theRelaxedProperty=value1");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void prefixWithoutPeriod() throws Exception {
load(RelaxedPropertiesRequiredConfigurationWithShortPrefix.class,
"spring.property=value1");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
// Enabled by default
public void enabledIfNotConfiguredOtherwise() {
load(EnabledIfNotConfiguredOtherwiseConfig.class);
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void enabledIfNotConfiguredOtherwiseWithConfig() {
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:false");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void enabledIfNotConfiguredOtherwiseWithConfigDifferentCase() {
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.my-property:FALSE");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
// Disabled by default
public void disableIfNotConfiguredOtherwise() {
load(DisabledIfNotConfiguredOtherwiseConfig.class);
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void disableIfNotConfiguredOtherwiseWithConfig() {
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:true");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void disableIfNotConfiguredOtherwiseWithConfigDifferentCase() {
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myproperty:TrUe");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void simpleValueIsSet() {
load(SimpleValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void caseInsensitive() {
load(SimpleValueConfig.class, "simple.myProperty:BaR");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void defaultValueIsSet() {
load(DefaultValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void defaultValueIsNotSet() {
load(DefaultValueConfig.class);
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void defaultValueIsSetDifferentValue() {
load(DefaultValueConfig.class, "simple.myProperty:another");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void prefix() {
load(PrefixValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void relaxedEnabledByDefault() {
load(PrefixValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void multiValuesAllSet() {
load(MultiValuesConfig.class, "simple.my-property:bar",
"simple.my-another-property:bar");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void multiValuesOnlyOneSet() {
load(MultiValuesConfig.class, "simple.my-property:bar");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void usingValueAttribute() throws Exception {
load(ValueAttribute.class, "some.property");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void nameOrValueMustBeSpecified() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectCause(hasMessage(containsString("The name or "
+ "value attribute of @ConditionalOnProperty must be specified")));
load(NoNameOrValueAttribute.class, "some.property");
}
@Test
public void nameAndValueMustNotBeSpecified() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectCause(hasMessage(containsString("The name and "
+ "value attributes of @ConditionalOnProperty are exclusive")));
load(NameAndValueAttribute.class, "some.property");
}
@Test
public void metaAnnotationConditionMatchesWhenPropertyIsSet() throws Exception {
load(MetaAnnotation.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue();
}
@Test
public void metaAnnotationConditionDoesNotMatchWhenPropertyIsNotSet()
throws Exception {
load(MetaAnnotation.class);
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyDirectPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyMetaPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void metaAndDirectAnnotationConditionDoesNotMatchWhenNeitherPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class);
assertThat(this.context.containsBean("foo")).isFalse();
}
@Test
public void metaAndDirectAnnotationConditionMatchesWhenBothPropertiesAreSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true",
"my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue();
}
private void load(Class<?> config, String... environment) {
EnvironmentTestUtils.addEnvironment(this.environment, environment);
this.context = new SpringApplicationBuilder(config).environment(this.environment)
.web(WebApplicationType.NONE).run();
}
@Configuration
@ConditionalOnProperty(name = { "property1", "property2" })
protected static class MultiplePropertiesRequiredConfiguration {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "spring.", name = "the-relaxed-property")
protected static class RelaxedPropertiesRequiredConfiguration {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "spring", name = "property")
protected static class RelaxedPropertiesRequiredConfigurationWithShortPrefix {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
// i.e ${simple.myProperty:true}
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "true", matchIfMissing = true)
static class EnabledIfNotConfiguredOtherwiseConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
// i.e ${simple.myProperty:false}
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "true", matchIfMissing = false)
static class DisabledIfNotConfiguredOtherwiseConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar")
static class SimpleValueConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(name = "simple.myProperty", havingValue = "bar", matchIfMissing = true)
static class DefaultValueConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "simple", name = "my-property", havingValue = "bar")
static class PrefixValueConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(prefix = "simple", name = { "my-property",
"my-another-property" }, havingValue = "bar")
static class MultiValuesConfig {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty("some.property")
protected static class ValueAttribute {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty
protected static class NoNameOrValueAttribute {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnProperty(value = "x", name = "y")
protected static class NameAndValueAttribute {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnMyFeature
protected static class MetaAnnotation {
@Bean
public String foo() {
return "foo";
}
}
@Configuration
@ConditionalOnMyFeature
@ConditionalOnProperty(prefix = "my.other.feature", name = "enabled", havingValue = "true", matchIfMissing = false)
protected static class MetaAnnotationAndDirectAnnotation {
@Bean
public String foo() {
return "foo";
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(prefix = "my.feature", name = "enabled", havingValue = "true", matchIfMissing = false)
public @interface ConditionalOnMyFeature {
}
}