[SPR-5914] ProfileValueUtils now properly ensures that class-level usage of @IfProfileValue overrides method-level usage.
This commit is contained in:
@@ -31,62 +31,64 @@ import java.lang.annotation.Target;
|
||||
* test will be enabled.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note: <code>@IfProfileValue</code> can be applied at either the
|
||||
* class or method level.
|
||||
* Note: <code>@IfProfileValue</code> can be applied at the class level,
|
||||
* the method level, or both. <code>@IfProfileValue</code> at the class
|
||||
* level overrides method-level usage of <code>@IfProfileValue</code> for
|
||||
* any methods within that class.
|
||||
* </p>
|
||||
* <p>
|
||||
* Examples: when using {@link SystemProfileValueSource} as the
|
||||
* {@link ProfileValueSource} implementation, you can configure a test method to
|
||||
* run only on Java VMs from Sun Microsystems as follows:
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* @IfProfileValue(name="java.vendor", value="Sun Microsystems Inc.")
|
||||
* @IfProfileValue(name = "java.vendor", value = "Sun Microsystems Inc.")
|
||||
* public void testSomething() {
|
||||
* // ...
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* You can alternatively configure <code>@IfProfileValue</code> with
|
||||
* <em>OR</em> semantics for multiple {@link #values() values} as follows
|
||||
* (assuming a {@link ProfileValueSource} has been appropriately configured for
|
||||
* the "test-groups" name):
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* @IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"})
|
||||
* @IfProfileValue(name = "test-groups", values = { "unit-tests", "integration-tests" })
|
||||
* public void testWhichRunsForUnitOrIntegrationTestGroups() {
|
||||
* // ...
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
* @since 2.0
|
||||
* @see ProfileValueSource
|
||||
* @see ProfileValueSourceConfiguration
|
||||
* @see ProfileValueUtils
|
||||
* @see AbstractAnnotationAwareTransactionalTests
|
||||
* @see org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests
|
||||
* @see org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Target( { ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface IfProfileValue {
|
||||
|
||||
/**
|
||||
* The <code>name</code> of the <em>profile value</em> against which to test.
|
||||
* The <code>name</code> of the <em>profile value</em> against which to
|
||||
* test.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* A single, permissible <code>value</code> of the <em>profile value</em>
|
||||
* for the given {@link #name() name}.
|
||||
* <p>Note: Assigning values to both {@link #value()} and {@link #values()}
|
||||
* <p>
|
||||
* Note: Assigning values to both {@link #value()} and {@link #values()}
|
||||
* will lead to a configuration conflict.
|
||||
*/
|
||||
String value() default "";
|
||||
@@ -94,7 +96,8 @@ public @interface IfProfileValue {
|
||||
/**
|
||||
* A list of all permissible <code>values</code> of the
|
||||
* <em>profile value</em> for the given {@link #name() name}.
|
||||
* <p>Note: Assigning values to both {@link #value()} and {@link #values()}
|
||||
* <p>
|
||||
* Note: Assigning values to both {@link #value()} and {@link #values()}
|
||||
* will lead to a configuration conflict.
|
||||
*/
|
||||
String[] values() default {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -28,7 +27,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* General utility methods for working with <em>profile values</em>.
|
||||
*
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
@@ -44,15 +43,15 @@ public abstract class ProfileValueUtils {
|
||||
/**
|
||||
* Retrieves the {@link ProfileValueSource} type for the specified
|
||||
* {@link Class test class} as configured via the
|
||||
* {@link ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}
|
||||
* annotation and instantiates a new instance of that type.
|
||||
* {@link ProfileValueSourceConfiguration
|
||||
* @ProfileValueSourceConfiguration} annotation and instantiates a new
|
||||
* instance of that type.
|
||||
* <p>
|
||||
* If
|
||||
* {@link ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}
|
||||
* is not present on the specified class or if a custom
|
||||
* {@link ProfileValueSource} is not declared, the default
|
||||
* {@link SystemProfileValueSource} will be returned instead.
|
||||
*
|
||||
* If {@link ProfileValueSourceConfiguration
|
||||
* @ProfileValueSourceConfiguration} is not present on the specified
|
||||
* class or if a custom {@link ProfileValueSource} is not declared, the
|
||||
* default {@link SystemProfileValueSource} will be returned instead.
|
||||
*
|
||||
* @param testClass The test class for which the ProfileValueSource should
|
||||
* be retrieved
|
||||
* @return the configured (or default) ProfileValueSource for the specified
|
||||
@@ -103,95 +102,92 @@ public abstract class ProfileValueUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the supplied <code>testClass</code> is <em>enabled</em>
|
||||
* in the current environment, as specified by the
|
||||
* {@link IfProfileValue @IfProfileValue} annotation at the class level.
|
||||
* Determine if the supplied <code>testClass</code> is <em>enabled</em> in
|
||||
* the current environment, as specified by the {@link IfProfileValue
|
||||
* @IfProfileValue} annotation at the class level.
|
||||
* <p>
|
||||
* Defaults to <code>true</code> if no
|
||||
* {@link IfProfileValue @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* Defaults to <code>true</code> if no {@link IfProfileValue
|
||||
* @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* @param testClass the test class
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the
|
||||
* current environment
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the current
|
||||
* environment
|
||||
*/
|
||||
public static boolean isTestEnabledInThisEnvironment(Class<?> testClass) {
|
||||
IfProfileValue ifProfileValue = testClass.getAnnotation(IfProfileValue.class);
|
||||
if (ifProfileValue == null) {
|
||||
return true;
|
||||
}
|
||||
ProfileValueSource profileValueSource = retrieveProfileValueSource(testClass);
|
||||
return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue);
|
||||
return isTestEnabledInThisEnvironment(retrieveProfileValueSource(testClass), ifProfileValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the supplied <code>testMethod</code> is <em>enabled</em>
|
||||
* in the current environment, as specified by the
|
||||
* {@link IfProfileValue @IfProfileValue} annotation, which may be declared
|
||||
* on the test method itself or at the class level.
|
||||
* Determine if the supplied <code>testMethod</code> is <em>enabled</em> in
|
||||
* the current environment, as specified by the {@link IfProfileValue
|
||||
* @IfProfileValue} annotation, which may be declared on the test
|
||||
* method itself or at the class level. Class-level usage overrides
|
||||
* method-level usage.
|
||||
* <p>
|
||||
* Defaults to <code>true</code> if no
|
||||
* {@link IfProfileValue @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* Defaults to <code>true</code> if no {@link IfProfileValue
|
||||
* @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* @param testMethod the test method
|
||||
* @param testClass the test class
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the
|
||||
* current environment
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the current
|
||||
* environment
|
||||
*/
|
||||
public static boolean isTestEnabledInThisEnvironment(Method testMethod, Class<?> testClass) {
|
||||
IfProfileValue ifProfileValue = testMethod.getAnnotation(IfProfileValue.class);
|
||||
if (ifProfileValue == null) {
|
||||
ifProfileValue = testClass.getAnnotation(IfProfileValue.class);
|
||||
if (ifProfileValue == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ProfileValueSource profileValueSource = retrieveProfileValueSource(testClass);
|
||||
return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue);
|
||||
return isTestEnabledInThisEnvironment(retrieveProfileValueSource(testClass), testMethod, testClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the supplied <code>testMethod</code> is <em>enabled</em>
|
||||
* in the current environment, as specified by the
|
||||
* {@link IfProfileValue @IfProfileValue} annotation, which may be declared
|
||||
* on the test method itself or at the class level.
|
||||
* Determine if the supplied <code>testMethod</code> is <em>enabled</em> in
|
||||
* the current environment, as specified by the {@link IfProfileValue
|
||||
* @IfProfileValue} annotation, which may be declared on the test
|
||||
* method itself or at the class level. Class-level usage overrides
|
||||
* method-level usage.
|
||||
* <p>
|
||||
* Defaults to <code>true</code> if no
|
||||
* {@link IfProfileValue @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* Defaults to <code>true</code> if no {@link IfProfileValue
|
||||
* @IfProfileValue} annotation is declared.
|
||||
*
|
||||
* @param profileValueSource the ProfileValueSource to use to determine if
|
||||
* the test is enabled
|
||||
* @param testMethod the test method
|
||||
* @param testClass the test class
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the
|
||||
* current environment
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the current
|
||||
* environment
|
||||
*/
|
||||
public static boolean isTestEnabledInThisEnvironment(ProfileValueSource profileValueSource, Method testMethod,
|
||||
Class<?> testClass) {
|
||||
|
||||
IfProfileValue ifProfileValue = testMethod.getAnnotation(IfProfileValue.class);
|
||||
if (ifProfileValue == null) {
|
||||
ifProfileValue = testClass.getAnnotation(IfProfileValue.class);
|
||||
if (ifProfileValue == null) {
|
||||
return true;
|
||||
}
|
||||
IfProfileValue ifProfileValue = testClass.getAnnotation(IfProfileValue.class);
|
||||
boolean classLevelEnabled = isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue);
|
||||
|
||||
if (classLevelEnabled) {
|
||||
ifProfileValue = testMethod.getAnnotation(IfProfileValue.class);
|
||||
return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue);
|
||||
}
|
||||
return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the <code>value</code> (or one of the <code>values</code>)
|
||||
* in the supplied {@link IfProfileValue @IfProfileValue} annotation is
|
||||
* in the supplied {@link IfProfileValue @IfProfileValue} annotation is
|
||||
* <em>enabled</em> in the current environment.
|
||||
*
|
||||
*
|
||||
* @param profileValueSource the ProfileValueSource to use to determine if
|
||||
* the test is enabled
|
||||
* @param ifProfileValue the annotation to introspect
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the
|
||||
* current environment
|
||||
* @param ifProfileValue the annotation to introspect; may be
|
||||
* <code>null</code>
|
||||
* @return <code>true</code> if the test is <em>enabled</em> in the current
|
||||
* environment or if the supplied <code>ifProfileValue</code> is
|
||||
* <code>null</code>
|
||||
*/
|
||||
private static boolean isTestEnabledInThisEnvironment(ProfileValueSource profileValueSource,
|
||||
IfProfileValue ifProfileValue) {
|
||||
|
||||
if (ifProfileValue == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String environmentValue = profileValueSource.get(ifProfileValue.name());
|
||||
String[] annotatedValues = ifProfileValue.values();
|
||||
if (StringUtils.hasLength(ifProfileValue.value())) {
|
||||
|
||||
Reference in New Issue
Block a user