Defaults to {@code false} so that test application contexts are not + * eagerly loaded unnecessarily. If an expression is based solely on system + * properties or environment variables or does not interact with beans in + * the test's application context, there is no need to load the context + * prematurely since doing so would be a waste of time if the test ends up + * being disabled. + * + * @see #expression + */ + boolean loadContext() default false; + } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java index 8185346574..1b9392a398 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/DisabledIfCondition.java @@ -61,7 +61,8 @@ public class DisabledIfCondition extends AbstractExpressionEvaluatingCondition { } private ConditionEvaluationResult evaluateDisabledIf(ExtensionContext context) { - return evaluateAnnotation(DisabledIf.class, DisabledIf::expression, DisabledIf::reason, false, context); + return evaluateAnnotation(DisabledIf.class, DisabledIf::expression, DisabledIf::reason, + DisabledIf::loadContext, false, context); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIf.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIf.java index bd8602d07c..f9d2c18dc7 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIf.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIf.java @@ -63,8 +63,8 @@ import org.springframework.core.annotation.AliasFor; public @interface EnabledIf { /** - * Alias for {@link #expression}; only intended to be used if an - * explicit {@link #reason} is not provided. + * Alias for {@link #expression}; only intended to be used if {@link #reason} + * and {@link #loadContext} are not specified. * * @see #expression */ @@ -96,6 +96,7 @@ public @interface EnabledIf { * and {@code @EnabledIf("true")} is logically meaningless. * * @see #reason + * @see #loadContext * @see #value */ @AliasFor("value") @@ -108,4 +109,19 @@ public @interface EnabledIf { */ String reason() default ""; + /** + * Whether the {@code ApplicationContext} associated with the current test + * should be eagerly loaded in order to evaluate the {@link #expression}. + * + *
Defaults to {@code false} so that test application contexts are not + * eagerly loaded unnecessarily. If an expression is based solely on system + * properties or environment variables or does not interact with beans in + * the test's application context, there is no need to load the context + * prematurely since doing so would be a waste of time if the test ends up + * being disabled. + * + * @see #expression + */ + boolean loadContext() default false; + } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java index aaba6b1f7a..b9eb00c48e 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/EnabledIfCondition.java @@ -60,7 +60,8 @@ public class EnabledIfCondition extends AbstractExpressionEvaluatingCondition { } private ConditionEvaluationResult evaluateEnabledIf(ExtensionContext context) { - return evaluateAnnotation(EnabledIf.class, EnabledIf::expression, EnabledIf::reason, true, context); + return evaluateAnnotation(EnabledIf.class, EnabledIf::expression, EnabledIf::reason, + EnabledIf::loadContext, true, context); } } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfConditionTestCase.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfConditionTestCase.java index 1104215e17..60b86bd3a7 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfConditionTestCase.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfConditionTestCase.java @@ -76,11 +76,26 @@ class DisabledIfConditionTestCase { @Test void invalidExpressionEvaluationType() { + String methodName = "nonBooleanOrStringExpression"; IllegalStateException exception = expectThrows(IllegalStateException.class, - () -> condition.evaluate(buildExtensionContext("nonBooleanOrStringExpression"))); + () -> condition.evaluate(buildExtensionContext(methodName))); + + Method method = ReflectionUtils.findMethod(getClass(), methodName); + + assertThat(exception.getMessage(), + is(equalTo("@DisabledIf(\"#{6 * 7}\") on " + method + " must evaluate to a String or a Boolean, not java.lang.Integer"))); + } + + @Test + void unsupportedStringEvaluationValue() { + String methodName = "stringExpressionThatIsNeitherTrueNorFalse"; + IllegalStateException exception = expectThrows(IllegalStateException.class, + () -> condition.evaluate(buildExtensionContext(methodName))); + + Method method = ReflectionUtils.findMethod(getClass(), methodName); assertThat(exception.getMessage(), - is(equalTo("@DisabledIf(\"#{6 * 7}\") must evaluate to a String or a Boolean, not java.lang.Integer"))); + is(equalTo("@DisabledIf(\"#{'enigma'}\") on " + method + " must evaluate to \"true\" or \"false\", not \"enigma\""))); } @Test @@ -151,6 +166,10 @@ class DisabledIfConditionTestCase { private void nonBooleanOrStringExpression() { } + @DisabledIf("#{'enigma'}") + private void stringExpressionThatIsNeitherTrueNorFalse() { + } + @DisabledIf(expression = "#{6 * 7 == 42}", reason = "Because... 42!") private void customReason() { } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfTestCase.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfTestCase.java index 0f7c9e1c18..497324be54 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfTestCase.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/DisabledIfTestCase.java @@ -23,7 +23,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.TestPropertySource; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.fail; /** * Integration tests which verify support for {@link DisabledIf @DisabledIf} @@ -63,13 +64,19 @@ class DisabledIfTestCase { } @Test - @DisabledIf("${foo}") + @DisabledIf("${__EnigmaPropertyShouldNotExist__:true}") + void disabledIfWithPropertyPlaceholderForNonexistentPropertyWithDefaultValue() { + fail("This test must be disabled"); + } + + @Test + @DisabledIf(expression = "${foo}", loadContext = true) void disabledIfWithPropertyPlaceholder() { fail("This test must be disabled"); } @Test - @DisabledIf("\t${foo} ") + @DisabledIf(expression = "\t${foo} ", loadContext = true) void disabledIfWithPropertyPlaceholderWithSurroundingWhitespace() { fail("This test must be disabled"); } @@ -105,13 +112,13 @@ class DisabledIfTestCase { } @Test - @DisabledIf("#{@booleanTrueBean}") + @DisabledIf(expression = "#{@booleanTrueBean}", loadContext = true) void disabledIfWithSpelBooleanTrueBean() { fail("This test must be disabled"); } @Test - @DisabledIf("#{@stringTrueBean}") + @DisabledIf(expression = "#{@stringTrueBean}", loadContext = true) void disabledIfWithSpelStringTrueBean() { fail("This test must be disabled"); } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/EnabledIfTestCase.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/EnabledIfTestCase.java index 13631320f6..cb6a8753bb 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/EnabledIfTestCase.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/EnabledIfTestCase.java @@ -18,6 +18,7 @@ package org.springframework.test.context.junit.jupiter; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.TestPropertySource; @@ -64,13 +65,19 @@ class EnabledIfTestCase { } @Test - @EnabledIf("${foo}") + @EnabledIf("${__EnigmaPropertyShouldNotExist__:false}") + void enabledIfWithPropertyPlaceholderForNonexistentPropertyWithDefaultValue() { + fail("This test must be disabled"); + } + + @Test + @EnabledIf(expression = "${foo}", loadContext = true) void enabledIfWithPropertyPlaceholder() { fail("This test must be disabled"); } @Test - @EnabledIf("\t${foo} ") + @EnabledIf(expression = "\t${foo} ", loadContext = true) void enabledIfWithPropertyPlaceholderWithSurroundingWhitespace() { fail("This test must be disabled"); } @@ -108,13 +115,13 @@ class EnabledIfTestCase { } @Test - @EnabledIf("#{@booleanFalseBean}") + @EnabledIf(expression = "#{@booleanFalseBean}", loadContext = true) void enabledIfWithSpelBooleanFalseBean() { fail("This test must be disabled"); } @Test - @EnabledIf("#{@stringFalseBean}") + @EnabledIf(expression = "#{@stringFalseBean}", loadContext = true) void enabledIfWithSpelStringFalseBean() { fail("This test must be disabled"); }