提交 a9fbbc55 编写于 作者: J Juergen Hoeller

Polishing

上级 3845eb3c
......@@ -23,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
......@@ -114,19 +113,16 @@ public class SpringClassRule implements TestRule {
/**
* Apply <em>class-level</em> features of the <em>Spring TestContext
* Framework</em> to the supplied {@code base} statement.
*
* <p>Specifically, this method retrieves the {@link TestContextManager}
* used by this rule and its associated {@link SpringMethodRule} and
* invokes the {@link TestContextManager#beforeTestClass() beforeTestClass()}
* and {@link TestContextManager#afterTestClass() afterTestClass()} methods
* on the {@code TestContextManager}.
*
* <p>In addition, this method checks whether the test is enabled in
* the current execution environment. This prevents classes with a
* non-matching {@code @IfProfileValue} annotation from running altogether,
* even skipping the execution of {@code beforeTestClass()} methods
* in {@code TestExecutionListeners}.
*
* @param base the base {@code Statement} that this rule should be applied to
* @param description a {@code Description} of the current test execution
* @return a statement that wraps the supplied {@code base} with class-level
......@@ -140,13 +136,10 @@ public class SpringClassRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
Class<?> testClass = description.getTestClass();
if (logger.isDebugEnabled()) {
logger.debug("Applying SpringClassRule to test class [" + testClass.getName() + "].");
logger.debug("Applying SpringClassRule to test class [" + testClass.getName() + "]");
}
validateSpringMethodRuleConfiguration(testClass);
TestContextManager testContextManager = getTestContextManager(testClass);
Statement statement = base;
......@@ -189,18 +182,19 @@ public class SpringClassRule implements TestRule {
return new TestContextManagerCacheEvictor(statement, testClass);
}
/**
* Throw an {@link IllegalStateException} if the supplied {@code testClass}
* does not declare a {@code public SpringMethodRule} field that is
* annotated with {@code @Rule}.
*/
private static final void validateSpringMethodRuleConfiguration(Class<?> testClass) {
private static void validateSpringMethodRuleConfiguration(Class<?> testClass) {
Field ruleField = null;
for (Field field : testClass.getFields()) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)
&& SpringMethodRule.class.isAssignableFrom(field.getType())) {
if (!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) &&
SpringMethodRule.class.isAssignableFrom(field.getType())) {
ruleField = field;
break;
}
......@@ -208,14 +202,14 @@ public class SpringClassRule implements TestRule {
if (ruleField == null) {
throw new IllegalStateException(String.format(
"Failed to find 'public SpringMethodRule' field in test class [%s]. "
+ "Consult the Javadoc for SpringClassRule for details.", testClass.getName()));
"Failed to find 'public SpringMethodRule' field in test class [%s]. " +
"Consult the javadoc for SpringClassRule for details.", testClass.getName()));
}
if (!ruleField.isAnnotationPresent(Rule.class)) {
throw new IllegalStateException(String.format(
"SpringMethodRule field [%s] must be annotated with JUnit's @Rule annotation. "
+ "Consult the Javadoc for SpringClassRule for details.", ruleField));
"SpringMethodRule field [%s] must be annotated with JUnit's @Rule annotation. " +
"Consult the javadoc for SpringClassRule for details.", ruleField));
}
}
......@@ -223,7 +217,7 @@ public class SpringClassRule implements TestRule {
* Get the {@link TestContextManager} associated with the supplied test class.
* @param testClass the test class to be managed; never {@code null}
*/
static final TestContextManager getTestContextManager(Class<?> testClass) {
static TestContextManager getTestContextManager(Class<?> testClass) {
Assert.notNull(testClass, "testClass must not be null");
synchronized (testContextManagerCache) {
TestContextManager testContextManager = testContextManagerCache.get(testClass);
......
......@@ -20,7 +20,6 @@ import java.lang.reflect.Field;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.ClassRule;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
......@@ -112,20 +111,17 @@ public class SpringMethodRule implements MethodRule {
* Apply <em>instance-level</em> and <em>method-level</em> features of
* the <em>Spring TestContext Framework</em> to the supplied {@code base}
* statement.
*
* <p>Specifically, this method invokes the
* {@link TestContextManager#prepareTestInstance prepareTestInstance()},
* {@link TestContextManager#beforeTestMethod beforeTestMethod()}, and
* {@link TestContextManager#afterTestMethod afterTestMethod()} methods
* on the {@code TestContextManager}, potentially with Spring timeouts
* and repetitions.
*
* <p>In addition, this method checks whether the test is enabled in
* the current execution environment. This prevents methods with a
* non-matching {@code @IfProfileValue} annotation from running altogether,
* even skipping the execution of {@code prepareTestInstance()} methods
* in {@code TestExecutionListeners}.
*
* @param base the base {@code Statement} that this rule should be applied to
* @param frameworkMethod the method which is about to be invoked on the test instance
* @param testInstance the current test instance
......@@ -140,14 +136,11 @@ public class SpringMethodRule implements MethodRule {
*/
@Override
public Statement apply(Statement base, FrameworkMethod frameworkMethod, Object testInstance) {
Class<?> testClass = testInstance.getClass();
if (logger.isDebugEnabled()) {
logger.debug("Applying SpringMethodRule to test method [" + frameworkMethod.getMethod() + "].");
logger.debug("Applying SpringMethodRule to test method [" + frameworkMethod.getMethod() + "]");
}
Class<?> testClass = testInstance.getClass();
validateSpringClassRuleConfiguration(testClass);
TestContextManager testContextManager = SpringClassRule.getTestContextManager(testClass);
Statement statement = base;
......@@ -166,8 +159,9 @@ public class SpringMethodRule implements MethodRule {
*/
private Statement withBeforeTestMethodCallbacks(Statement statement, FrameworkMethod frameworkMethod,
Object testInstance, TestContextManager testContextManager) {
return new RunBeforeTestMethodCallbacks(statement, testInstance, frameworkMethod.getMethod(),
testContextManager);
return new RunBeforeTestMethodCallbacks(
statement, testInstance, frameworkMethod.getMethod(), testContextManager);
}
/**
......@@ -176,7 +170,9 @@ public class SpringMethodRule implements MethodRule {
*/
private Statement withAfterTestMethodCallbacks(Statement statement, FrameworkMethod frameworkMethod,
Object testInstance, TestContextManager testContextManager) {
return new RunAfterTestMethodCallbacks(statement, testInstance, frameworkMethod.getMethod(), testContextManager);
return new RunAfterTestMethodCallbacks(
statement, testInstance, frameworkMethod.getMethod(), testContextManager);
}
/**
......@@ -185,6 +181,7 @@ public class SpringMethodRule implements MethodRule {
*/
private Statement withTestInstancePreparation(Statement statement, Object testInstance,
TestContextManager testContextManager) {
return new RunPrepareTestInstanceCallbacks(statement, testInstance, testContextManager);
}
......@@ -216,12 +213,13 @@ public class SpringMethodRule implements MethodRule {
return new ProfileValueChecker(statement, testInstance.getClass(), frameworkMethod.getMethod());
}
/**
* Throw an {@link IllegalStateException} if the supplied {@code testClass}
* does not declare a {@code public static final SpringClassRule} field
* that is annotated with {@code @ClassRule}.
*/
private static final SpringClassRule validateSpringClassRuleConfiguration(Class<?> testClass) {
private static SpringClassRule validateSpringClassRuleConfiguration(Class<?> testClass) {
Field ruleField = null;
for (Field field : testClass.getFields()) {
......@@ -233,14 +231,14 @@ public class SpringMethodRule implements MethodRule {
if (ruleField == null) {
throw new IllegalStateException(String.format(
"Failed to find 'public static final SpringClassRule' field in test class [%s]. "
+ "Consult the Javadoc for SpringClassRule for details.", testClass.getName()));
"Failed to find 'public static final SpringClassRule' field in test class [%s]. " +
"Consult the javadoc for SpringClassRule for details.", testClass.getName()));
}
if (!ruleField.isAnnotationPresent(ClassRule.class)) {
throw new IllegalStateException(String.format(
"SpringClassRule field [%s] must be annotated with JUnit's @ClassRule annotation. "
+ "Consult the Javadoc for SpringClassRule for details.", ruleField));
"SpringClassRule field [%s] must be annotated with JUnit's @ClassRule annotation. " +
"Consult the javadoc for SpringClassRule for details.", ruleField));
}
return (SpringClassRule) ReflectionUtils.getField(ruleField, null);
......
......@@ -16,6 +16,7 @@
package org.springframework.test.context.junit4.statements;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.junit.Assume;
......@@ -49,9 +50,8 @@ public class ProfileValueChecker extends Statement {
/**
* Construct a new {@code ProfileValueChecker} statement.
*
* @param next the next {@code Statement} in the execution chain; never
* {@code null}
* @param next the next {@code Statement} in the execution chain;
* never {@code null}
* @param testClass the test class to check; never {@code null}
* @param testMethod the test method to check; may be {@code null} if
* this {@code ProfileValueChecker} is being applied at the class level
......@@ -81,21 +81,22 @@ public class ProfileValueChecker extends Statement {
@Override
public void evaluate() throws Throwable {
if (this.testMethod == null) {
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(testClass)) {
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(this.testClass)) {
// Invoke assumeTrue() with false to avoid direct reference to JUnit's
// AssumptionViolatedException which exists in two packages as of JUnit 4.12.
Annotation ann = AnnotationUtils.findAnnotation(this.testClass, IfProfileValue.class);
Assume.assumeTrue(String.format(
"Profile configured via [%s] is not enabled in this environment for test class [%s].",
AnnotationUtils.findAnnotation(testClass, IfProfileValue.class), testClass.getName()), false);
"Profile configured via [%s] is not enabled in this environment for test class [%s].",
ann, this.testClass.getName()), false);
}
}
else {
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(testMethod, testClass)) {
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(this.testMethod, this.testClass)) {
// Invoke assumeTrue() with false to avoid direct reference to JUnit's
// AssumptionViolatedException which exists in two packages as of JUnit 4.12.
Assume.assumeTrue(String.format(
"Profile configured via @IfProfileValue is not enabled in this environment for test method [%s].",
testMethod), false);
"Profile configured via @IfProfileValue is not enabled in this environment for test method [%s].",
this.testMethod), false);
}
}
......
......@@ -32,10 +32,10 @@ import org.springframework.test.context.TestContextManager;
*
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
*
* @see #evaluate()
* @see RunBeforeTestClassCallbacks
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
* @see RunBeforeTestClassCallbacks
*/
public class RunAfterTestClassCallbacks extends Statement {
......@@ -46,7 +46,6 @@ public class RunAfterTestClassCallbacks extends Statement {
/**
* Construct a new {@code RunAfterTestClassCallbacks} statement.
*
* @param next the next {@code Statement} in the execution chain
* @param testContextManager the TestContextManager upon which to call
* {@code afterTestClass()}
......@@ -56,6 +55,7 @@ public class RunAfterTestClassCallbacks extends Statement {
this.testContextManager = testContextManager;
}
/**
* Evaluate the next {@link Statement} in the execution chain (typically an instance of
* {@link org.junit.internal.runners.statements.RunAfters RunAfters}), catching any
......@@ -69,15 +69,15 @@ public class RunAfterTestClassCallbacks extends Statement {
try {
this.next.evaluate();
}
catch (Throwable e) {
errors.add(e);
catch (Throwable ex) {
errors.add(ex);
}
try {
this.testContextManager.afterTestClass();
}
catch (Exception e) {
errors.add(e);
catch (Throwable ex) {
errors.add(ex);
}
if (errors.isEmpty()) {
......
......@@ -33,10 +33,10 @@ import org.springframework.test.context.TestContextManager;
*
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
*
* @see #evaluate()
* @see RunBeforeTestMethodCallbacks
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
* @see RunBeforeTestMethodCallbacks
*/
public class RunAfterTestMethodCallbacks extends Statement {
......@@ -51,7 +51,6 @@ public class RunAfterTestMethodCallbacks extends Statement {
/**
* Construct a new {@code RunAfterTestMethodCallbacks} statement.
*
* @param next the next {@code Statement} in the execution chain
* @param testInstance the current test instance (never {@code null})
* @param testMethod the test method which has just been executed on the
......@@ -61,12 +60,14 @@ public class RunAfterTestMethodCallbacks extends Statement {
*/
public RunAfterTestMethodCallbacks(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}
/**
* Evaluate the next {@link Statement} in the execution chain (typically an instance of
* {@link org.junit.internal.runners.statements.RunAfters RunAfters}), catching any
......@@ -84,16 +85,16 @@ public class RunAfterTestMethodCallbacks extends Statement {
try {
this.next.evaluate();
}
catch (Throwable e) {
testException = e;
errors.add(e);
catch (Throwable ex) {
testException = ex;
errors.add(ex);
}
try {
this.testContextManager.afterTestMethod(this.testInstance, this.testMethod, testException);
}
catch (Exception e) {
errors.add(e);
catch (Throwable ex) {
errors.add(ex);
}
if (errors.isEmpty()) {
......
......@@ -26,10 +26,10 @@ import org.springframework.test.context.TestContextManager;
* by calling {@link TestContextManager#beforeTestClass() beforeTestClass()} on the
* supplied {@link TestContextManager}.
*
* @see #evaluate()
* @see RunAfterTestMethodCallbacks
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
* @see RunAfterTestMethodCallbacks
*/
public class RunBeforeTestClassCallbacks extends Statement {
......@@ -40,7 +40,6 @@ public class RunBeforeTestClassCallbacks extends Statement {
/**
* Construct a new {@code RunBeforeTestClassCallbacks} statement.
*
* @param next the next {@code Statement} in the execution chain
* @param testContextManager the TestContextManager upon which to call
* {@code beforeTestClass()}
......@@ -50,6 +49,7 @@ public class RunBeforeTestClassCallbacks extends Statement {
this.testContextManager = testContextManager;
}
/**
* Invoke {@link TestContextManager#beforeTestClass()} and then evaluate
* the next {@link Statement} in the execution chain (typically an instance
......
......@@ -28,10 +28,10 @@ import org.springframework.test.context.TestContextManager;
* by calling {@link TestContextManager#beforeTestMethod(Object, Method)
* beforeTestMethod()} on the supplied {@link TestContextManager}.
*
* @see #evaluate()
* @see RunAfterTestMethodCallbacks
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
* @see RunAfterTestMethodCallbacks
*/
public class RunBeforeTestMethodCallbacks extends Statement {
......@@ -46,7 +46,6 @@ public class RunBeforeTestMethodCallbacks extends Statement {
/**
* Construct a new {@code RunBeforeTestMethodCallbacks} statement.
*
* @param next the next {@code Statement} in the execution chain
* @param testInstance the current test instance (never {@code null})
* @param testMethod the test method which is about to be executed on the
......@@ -56,12 +55,14 @@ public class RunBeforeTestMethodCallbacks extends Statement {
*/
public RunBeforeTestMethodCallbacks(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}
/**
* Invoke {@link TestContextManager#beforeTestMethod(Object, Method)}
* and then evaluate the next {@link Statement} in the execution chain
......
......@@ -26,9 +26,9 @@ import org.springframework.test.context.TestContextManager;
* execution chain by calling {@link TestContextManager#prepareTestInstance(Object)
* prepareTestInstance()} on the supplied {@link TestContextManager}.
*
* @see #evaluate()
* @author Sam Brannen
* @since 4.2
* @see #evaluate()
*/
public class RunPrepareTestInstanceCallbacks extends Statement {
......@@ -41,7 +41,6 @@ public class RunPrepareTestInstanceCallbacks extends Statement {
/**
* Construct a new {@code RunPrepareTestInstanceCallbacks} statement.
*
* @param next the next {@code Statement} in the execution chain; never {@code null}
* @param testInstance the current test instance; never {@code null}
* @param testContextManager the {@code TestContextManager} upon which to call
......@@ -53,6 +52,7 @@ public class RunPrepareTestInstanceCallbacks extends Statement {
this.testContextManager = testContextManager;
}
/**
* Invoke {@link TestContextManager#prepareTestInstance(Object)} and
* then evaluate the next {@link Statement} in the execution chain
......
......@@ -35,9 +35,9 @@ import org.springframework.util.Assert;
* the next {@code statement} will be executed in the same thread as the
* caller and will therefore not be aborted preemptively.
*
* @see #evaluate()
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
*/
public class SpringFailOnTimeout extends Statement {
......@@ -50,7 +50,6 @@ public class SpringFailOnTimeout extends Statement {
* Construct a new {@code SpringFailOnTimeout} statement for the supplied
* {@code testMethod}, retrieving the configured timeout from the
* {@code @Timed} annotation on the supplied method.
*
* @param next the next {@code Statement} in the execution chain
* @param testMethod the current test method
* @see TestAnnotationUtils#getTimeout(Method)
......@@ -64,7 +63,6 @@ public class SpringFailOnTimeout extends Statement {
* {@code timeout}.
* <p>If the supplied {@code timeout} is {@code 0}, the execution of the
* {@code next} statement will not be timed.
*
* @param next the next {@code Statement} in the execution chain; never {@code null}
* @param timeout the configured {@code timeout} for the current test, in milliseconds;
* never negative
......@@ -76,6 +74,7 @@ public class SpringFailOnTimeout extends Statement {
this.timeout = timeout;
}
/**
* Evaluate the next {@link Statement statement} in the execution chain
* (typically an instance of {@link SpringRepeat}) and throw a
......@@ -96,7 +95,7 @@ public class SpringFailOnTimeout extends Statement {
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > this.timeout) {
throw new TimeoutException(
String.format("Test took %s ms; limit was %s ms.", elapsed, this.timeout));
String.format("Test took %s ms; limit was %s ms.", elapsed, this.timeout));
}
}
}
......
......@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.runners.model.Statement;
import org.springframework.test.annotation.TestAnnotationUtils;
......@@ -30,9 +29,9 @@ import org.springframework.test.annotation.TestAnnotationUtils;
* for Spring's {@link org.springframework.test.annotation.Repeat @Repeat}
* annotation by repeating the test the specified number of times.
*
* @see #evaluate()
* @author Sam Brannen
* @since 3.0
* @see #evaluate()
*/
public class SpringRepeat extends Statement {
......@@ -49,7 +48,6 @@ public class SpringRepeat extends Statement {
* Construct a new {@code SpringRepeat} statement for the supplied
* {@code testMethod}, retrieving the configured repeat count from the
* {@code @Repeat} annotation on the supplied method.
*
* @param next the next {@code Statement} in the execution chain
* @param testMethod the current test method
* @see TestAnnotationUtils#getRepeatCount(Method)
......@@ -61,7 +59,6 @@ public class SpringRepeat extends Statement {
/**
* Construct a new {@code SpringRepeat} statement for the supplied
* {@code testMethod} and {@code repeat} count.
*
* @param next the next {@code Statement} in the execution chain
* @param testMethod the current test method
* @param repeat the configured repeat count for the current test method
......@@ -72,6 +69,7 @@ public class SpringRepeat extends Statement {
this.repeat = Math.max(1, repeat);
}
/**
* Evaluate the next {@link Statement statement} in the execution chain
* repeatedly, using the specified repeat count.
......@@ -81,7 +79,7 @@ public class SpringRepeat extends Statement {
for (int i = 0; i < this.repeat; i++) {
if (this.repeat > 1 && logger.isInfoEnabled()) {
logger.info(String.format("Repetition %d of test %s#%s()", (i + 1),
this.testMethod.getDeclaringClass().getSimpleName(), this.testMethod.getName()));
this.testMethod.getDeclaringClass().getSimpleName(), this.testMethod.getName()));
}
this.next.evaluate();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册