Remove hard configuration validation from SpringClassRule/MethodRule

Issue: SPR-16967
This commit is contained in:
Juergen Hoeller 2018-06-28 13:36:43 +02:00
parent 08e1c8cfaf
commit b0ece0e967
2 changed files with 5 additions and 85 deletions

View File

@ -16,16 +16,11 @@
package org.springframework.test.context.junit4.rules;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
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;
import org.junit.runners.model.Statement;
@ -35,7 +30,6 @@ import org.springframework.test.context.junit4.statements.ProfileValueChecker;
import org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks;
import org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@code SpringClassRule} is a custom JUnit {@link TestRule} that supports
@ -95,13 +89,7 @@ public class SpringClassRule implements TestRule {
/**
* Cache of {@code TestContextManagers} keyed by test class.
*/
private static final Map<Class<?>, TestContextManager> testContextManagerCache =
new ConcurrentHashMap<>(64);
static {
Assert.state(ClassUtils.isPresent("org.junit.internal.Throwables", SpringClassRule.class.getClassLoader()),
"SpringClassRule requires JUnit 4.12 or higher.");
}
private static final Map<Class<?>, TestContextManager> testContextManagerCache = new ConcurrentHashMap<>(64);
/**
@ -133,7 +121,6 @@ public class SpringClassRule implements TestRule {
if (logger.isDebugEnabled()) {
logger.debug("Applying SpringClassRule to test class [" + testClass.getName() + "]");
}
validateSpringMethodRuleConfiguration(testClass);
TestContextManager testContextManager = getTestContextManager(testClass);
Statement statement = base;
@ -176,37 +163,12 @@ public class SpringClassRule implements TestRule {
return new TestContextManagerCacheEvictor(next, 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 void validateSpringMethodRuleConfiguration(Class<?> testClass) {
Field ruleField = findSpringMethodRuleField(testClass).orElseThrow(() ->
new IllegalStateException(String.format(
"Failed to find 'public SpringMethodRule' field in test class [%s]. " +
"Consult the javadoc for SpringClassRule for details.", testClass.getName())));
Assert.state(ruleField.isAnnotationPresent(Rule.class), () -> String.format(
"SpringMethodRule field [%s] must be annotated with JUnit's @Rule annotation. " +
"Consult the javadoc for SpringClassRule for details.", ruleField));
}
private static Optional<Field> findSpringMethodRuleField(Class<?> testClass) {
return Arrays.stream(testClass.getFields())
.filter(field -> !Modifier.isStatic(field.getModifiers()))
.filter(field -> Modifier.isPublic(field.getModifiers()))
.filter(field -> SpringMethodRule.class.isAssignableFrom(field.getType()))
.findFirst();
}
/**
* Get the {@link TestContextManager} associated with the supplied test class.
* @param testClass the test class to be managed; never {@code null}
*/
static TestContextManager getTestContextManager(Class<?> testClass) {
Assert.notNull(testClass, "testClass must not be null");
Assert.notNull(testClass, "Test Class must not be null");
return testContextManagerCache.computeIfAbsent(testClass, TestContextManager::new);
}
@ -217,7 +179,6 @@ public class SpringClassRule implements TestRule {
private final Class<?> testClass;
TestContextManagerCacheEvictor(Statement next, Class<?> testClass) {
this.next = next;
this.testClass = testClass;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@ -16,14 +16,10 @@
package org.springframework.test.context.junit4.rules;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
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;
import org.junit.runners.model.Statement;
@ -35,9 +31,6 @@ import org.springframework.test.context.junit4.statements.RunBeforeTestMethodCal
import org.springframework.test.context.junit4.statements.RunPrepareTestInstanceCallbacks;
import org.springframework.test.context.junit4.statements.SpringFailOnTimeout;
import org.springframework.test.context.junit4.statements.SpringRepeat;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* {@code SpringMethodRule} is a custom JUnit 4 {@link MethodRule} that
@ -103,11 +96,6 @@ public class SpringMethodRule implements MethodRule {
private static final Log logger = LogFactory.getLog(SpringMethodRule.class);
static {
Assert.state(ClassUtils.isPresent("org.junit.internal.Throwables", SpringMethodRule.class.getClassLoader()),
"SpringMethodRule requires JUnit 4.12 or higher.");
}
/**
* Apply <em>instance-level</em> and <em>method-level</em> features of
@ -143,7 +131,6 @@ public class SpringMethodRule implements MethodRule {
logger.debug("Applying SpringMethodRule to test method [" + testMethod + "]");
}
Class<?> testClass = testInstance.getClass();
validateSpringClassRuleConfiguration(testClass);
TestContextManager testContextManager = SpringClassRule.getTestContextManager(testClass);
Statement statement = base;
@ -182,8 +169,8 @@ public class SpringMethodRule implements MethodRule {
* Wrap the supplied {@link Statement} with a {@code RunPrepareTestInstanceCallbacks} statement.
* @see RunPrepareTestInstanceCallbacks
*/
private Statement withTestInstancePreparation(Statement next, Object testInstance,
TestContextManager testContextManager) {
private Statement withTestInstancePreparation(
Statement next, Object testInstance, TestContextManager testContextManager) {
return new RunPrepareTestInstanceCallbacks(next, testInstance, testContextManager);
}
@ -216,32 +203,4 @@ public class SpringMethodRule implements MethodRule {
return new ProfileValueChecker(next, testInstance.getClass(), testMethod);
}
/**
* 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 SpringClassRule validateSpringClassRuleConfiguration(Class<?> testClass) {
Field ruleField = findSpringClassRuleField(testClass).orElseThrow(() ->
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())));
Assert.state(ruleField.isAnnotationPresent(ClassRule.class), () -> String.format(
"SpringClassRule field [%s] must be annotated with JUnit's @ClassRule annotation. " +
"Consult the javadoc for SpringClassRule for details.", ruleField));
Object result = ReflectionUtils.getField(ruleField, null);
Assert.state(result instanceof SpringClassRule, "SpringClassRule field mismatch");
return (SpringClassRule) result;
}
private static Optional<Field> findSpringClassRuleField(Class<?> testClass) {
return Arrays.stream(testClass.getFields())
.filter(ReflectionUtils::isPublicStaticFinal)
.filter(field -> SpringClassRule.class.isAssignableFrom(field.getType()))
.findFirst();
}
}