From f4fee621abfa2b274dde1e2a54e293ef0fb763c1 Mon Sep 17 00:00:00 2001 From: shyamz-22 Date: Sat, 16 Dec 2017 22:54:41 +0100 Subject: [PATCH] Add Unit tests to Conditional on Profile - Ignores order of profile - validates value attribute - Works only with more than one profile --- .../ActiveOnProfilesCondition.java | 22 --- ...les.java => ConditionalOnAllProfiles.java} | 8 +- .../ConditionalOnAllProfilesCondition.java | 46 ++++++ .../conditional/ConditionalApplication.java | 54 ++----- .../ConditionalApplicationTests.java | 34 ----- ...ConditionalOnAllProfilesConditionTest.java | 137 ++++++++++++++++++ .../DefaultSpringProfileBehaviorTests.java | 12 +- 7 files changed, 207 insertions(+), 106 deletions(-) delete mode 100644 src/main/java/io/github/shyamz/conditional/ActiveOnProfilesCondition.java rename src/main/java/io/github/shyamz/conditional/{ConditionalOnProfiles.java => ConditionalOnAllProfiles.java} (73%) create mode 100644 src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfilesCondition.java delete mode 100644 src/test/java/io/github/shyamz/conditional/ConditionalApplicationTests.java create mode 100644 src/test/java/io/github/shyamz/conditional/ConditionalOnAllProfilesConditionTest.java diff --git a/src/main/java/io/github/shyamz/conditional/ActiveOnProfilesCondition.java b/src/main/java/io/github/shyamz/conditional/ActiveOnProfilesCondition.java deleted file mode 100644 index 4878852..0000000 --- a/src/main/java/io/github/shyamz/conditional/ActiveOnProfilesCondition.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.shyamz.conditional; - - -import org.springframework.context.annotation.Condition; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.core.type.AnnotatedTypeMetadata; - -import java.util.Arrays; -import java.util.Map; - - -public class ActiveOnProfilesCondition implements Condition { - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - Map attributes - = metadata.getAnnotationAttributes(ConditionalOnProfiles.class.getName()); - String[] profilesToBeActive = (String[]) attributes.get("value"); - final String[] activeProfiles = context.getEnvironment().getActiveProfiles(); - return (Arrays.equals(activeProfiles, profilesToBeActive)); - } -} diff --git a/src/main/java/io/github/shyamz/conditional/ConditionalOnProfiles.java b/src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfiles.java similarity index 73% rename from src/main/java/io/github/shyamz/conditional/ConditionalOnProfiles.java rename to src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfiles.java index 2121a97..f1a8469 100644 --- a/src/main/java/io/github/shyamz/conditional/ConditionalOnProfiles.java +++ b/src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfiles.java @@ -10,7 +10,7 @@ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) -@Conditional(ActiveOnProfilesCondition.class) -public @interface ConditionalOnProfiles { - String[] value() default {}; - } +@Conditional(ConditionalOnAllProfilesCondition.class) +public @interface ConditionalOnAllProfiles { + String[] value(); +} diff --git a/src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfilesCondition.java b/src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfilesCondition.java new file mode 100644 index 0000000..43e7741 --- /dev/null +++ b/src/main/java/io/github/shyamz/conditional/ConditionalOnAllProfilesCondition.java @@ -0,0 +1,46 @@ +package io.github.shyamz.conditional; + + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + + +public class ConditionalOnAllProfilesCondition implements Condition { + + private List currentProfiles = new ArrayList<>(); + private List activeProfiles = new ArrayList<>(); + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + Map attributes = metadata + .getAnnotationAttributes(ConditionalOnAllProfiles.class.getName()); + + populateCurrentProfiles((String[]) attributes.get("value")); + populateActiveProfiles(context.getEnvironment().getActiveProfiles()); + + return currentProfiles.stream().allMatch(activeProfiles::contains); + } + + private void populateCurrentProfiles(String[] attributeValues) { + currentProfiles.clear(); + currentProfiles.addAll(Arrays.asList(attributeValues)); + validateCurrentProfiles(); + } + + private void validateCurrentProfiles() { + if (currentProfiles.isEmpty() || currentProfiles.size() == 1) { + throw new RuntimeException("'value' attributes need more than one 'profile' values. For just one profile use '@Profile' annotation"); + } + } + + private void populateActiveProfiles(String[] activeProfileValues) { + activeProfiles.clear(); + activeProfiles.addAll(Arrays.asList(activeProfileValues)); + } +} diff --git a/src/test/java/io/github/shyamz/conditional/ConditionalApplication.java b/src/test/java/io/github/shyamz/conditional/ConditionalApplication.java index 88f5a56..3f7cff0 100644 --- a/src/test/java/io/github/shyamz/conditional/ConditionalApplication.java +++ b/src/test/java/io/github/shyamz/conditional/ConditionalApplication.java @@ -10,46 +10,20 @@ @SpringBootApplication public class ConditionalApplication { + @Bean + @ConditionalOnAllProfiles(value = {"A", "B"}) + @Primary + public ConditionalBean conditionalOnAB() { + return () -> "AB"; + } - @Bean - @ConditionalOnProfiles(value = {"A", "B"}) - @Primary - public ConditionalBean conditionalOnAB() - { - return new ConditionalBean() { - @Override - public String getValue() { - return "AB"; - } - }; - } + @Bean + @Profile(value = {"A"}) + public ConditionalBean conditionalOnA() { + return () -> "A"; + } - @Bean - @ConditionalOnProfiles - @Primary - public ConditionalBean conditionalOnDefault() - { - return new ConditionalBean() { - @Override - public String getValue() { - return "Default"; - } - }; - } - - @Bean - @Profile(value = {"A"}) - public ConditionalBean conditionalOnA() - { - return new ConditionalBean() { - @Override - public String getValue() { - return "A"; - } - }; - } - - public static void main(String[] args) { - SpringApplication.run(ConditionalApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(ConditionalApplication.class, args); + } } diff --git a/src/test/java/io/github/shyamz/conditional/ConditionalApplicationTests.java b/src/test/java/io/github/shyamz/conditional/ConditionalApplicationTests.java deleted file mode 100644 index a4826dc..0000000 --- a/src/test/java/io/github/shyamz/conditional/ConditionalApplicationTests.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.shyamz.conditional; - -import io.github.shyamz.conditional.service.ConditionalBean; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.core.env.Environment; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class ConditionalApplicationTests { - - @Autowired - Environment environment; - - @Autowired - ConditionalBean conditionalBean; - - @Test - public void generatesDefaultConditionalBean_whenNoProfileIsActive() { - - String[] activeProfiles = environment.getActiveProfiles(); - assertThat(activeProfiles.length, is(0)); - assertThat(conditionalBean.getValue(), equalTo("Default")); - - } - -} diff --git a/src/test/java/io/github/shyamz/conditional/ConditionalOnAllProfilesConditionTest.java b/src/test/java/io/github/shyamz/conditional/ConditionalOnAllProfilesConditionTest.java new file mode 100644 index 0000000..7976b0d --- /dev/null +++ b/src/test/java/io/github/shyamz/conditional/ConditionalOnAllProfilesConditionTest.java @@ -0,0 +1,137 @@ +package io.github.shyamz.conditional; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.util.MultiValueMap; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + + +public class ConditionalOnAllProfilesConditionTest { + + private ConditionalOnAllProfilesCondition subject; + + @Before + public void setUp() throws Exception { + subject = new ConditionalOnAllProfilesCondition(); + } + + @Test + public void throwsExceptionForEmptyProfileList() throws Exception { + assertThatThrownBy( + () -> subject.matches(mockConditionContext(), mockAnnotatedTypeMetaData())) + .isExactlyInstanceOf(RuntimeException.class) + .hasMessage("'value' attributes need more than one 'profile' values. For just one profile use '@Profile' annotation"); + } + + @Test + public void throwsExceptionForOneProfile() throws Exception { + assertThatThrownBy( + () -> subject.matches(mockConditionContext(), mockAnnotatedTypeMetaData("test"))) + .isExactlyInstanceOf(RuntimeException.class) + .hasMessage("'value' attributes need more than one 'profile' values. For just one profile use '@Profile' annotation"); + } + + @Test + public void returnsTrueIfCurrentProfilesAreEqual() throws Exception { + assertThat(subject.matches(mockConditionContext("test", "local"), + mockAnnotatedTypeMetaData("test", "local"))).isTrue(); + } + + @Test + public void returnsTrueIfCurrentProfilesAreEqualButInDifferentOrder() throws Exception { + assertThat(subject.matches(mockConditionContext("test", "local"), + mockAnnotatedTypeMetaData("local", "test"))).isTrue(); + } + + @Test + public void returnsTrueIfCurrentProfilesAreSubsetOfActiveProfiles() throws Exception { + assertThat(subject.matches(mockConditionContext("test", "local", "pact"), + mockAnnotatedTypeMetaData("local", "test"))).isTrue(); + } + + @Test + public void returnsFalseIfCurrentProfilesAreNotSubsetOfActiveProfiles() throws Exception { + assertThat(subject.matches(mockConditionContext("test", "local"), + mockAnnotatedTypeMetaData("local", "test", "pact"))).isFalse(); + } + + @Test + public void returnsFalseIfCurrentProfilesAreDifferent() throws Exception { + assertThat(subject.matches(mockConditionContext("test", "local"), mockAnnotatedTypeMetaData("cloud", "acceptance"))).isFalse(); + } + + private ConditionContext mockConditionContext(String... activeProfiles) { + return new ConditionContext() { + + @Override + public BeanDefinitionRegistry getRegistry() { + return null; + } + + @Override + public ConfigurableListableBeanFactory getBeanFactory() { + return null; + } + + @Override + public Environment getEnvironment() { + MockEnvironment environment = new MockEnvironment(); + environment.withProperty("spring.profiles.active", String.join(",", activeProfiles)); + return environment; + } + + @Override + public ResourceLoader getResourceLoader() { + return null; + } + + @Override + public ClassLoader getClassLoader() { + return null; + } + }; + + } + + private AnnotatedTypeMetadata mockAnnotatedTypeMetaData(String... currentProfiles) { + return new AnnotatedTypeMetadata() { + @Override + public boolean isAnnotated(String annotationName) { + return true; + } + + @Override + public Map getAnnotationAttributes(String annotationName) { + return Collections.singletonMap("value", currentProfiles); + } + + @Override + public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + return null; + } + + @Override + public MultiValueMap getAllAnnotationAttributes(String annotationName) { + return null; + } + + @Override + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { + return null; + } + }; + } + +} \ No newline at end of file diff --git a/src/test/java/io/github/shyamz/conditional/DefaultSpringProfileBehaviorTests.java b/src/test/java/io/github/shyamz/conditional/DefaultSpringProfileBehaviorTests.java index 83d3dc6..ec1226a 100644 --- a/src/test/java/io/github/shyamz/conditional/DefaultSpringProfileBehaviorTests.java +++ b/src/test/java/io/github/shyamz/conditional/DefaultSpringProfileBehaviorTests.java @@ -16,12 +16,12 @@ @ActiveProfiles({"A"}) public class DefaultSpringProfileBehaviorTests { - @Autowired - ConditionalBean conditionalBean; + @Autowired + private ConditionalBean conditionalBean; - @Test - public void generatesConditionalBeanA_whenOnlyProfileAIsActive() { - assertThat(conditionalBean.getValue(), equalTo("A")); - } + @Test + public void generatesConditionalBeanA_whenOnlyProfileAIsActive() { + assertThat(conditionalBean.getValue(), equalTo("A")); + } }