package org.springframework.issues;
import java.lang.reflect.Method;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.springframework.test.context.TestContextManager;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* WARNING: PROOF OF CONCEPT. DO NOT ASSUME PRODUCTION CODE ;)
*
* A {@Rule} alternative to {@link SpringJUnit4ClassRunner}.
* <p>
* Currently used as follows:
*
* <pre>
* @Rule
* public static SpringContextRule rule = new SpringContextRule();
* </pre>
*
* Code borrowed from SPR-7731. Note that {@link MethodRule} is deprecated in recent versions of JUnit but there is some
* discussion about whether it ought to be re-instated (<a href="https://github.com/KentBeck/junit/issues/351">on
* github</a>).
*
* @author Neale Upstone (skype: neale87)
* @author Dave Syer
*/
public class SpringContextRule implements MethodRule {
// private static final Log logger = LogFactory.getLog(SpringContextRule.class);
private TestContextManager testContextManager;
/**
* Currently the only way to create a SpringContextRule. The rule will look for the usual Spring annotations etc on
* the test classes that this rule is applied to.
*/
public SpringContextRule() {
}
public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
// TODO: clean this up
if (testContextManager == null) {
testContextManager = createTestContextManager(target.getClass());
}
return new Statement() {
@Override
public void evaluate() throws Throwable {
Method testMethod = method.getMethod();
getTestContextManager().prepareTestInstance(target);
getTestContextManager().beforeTestMethod(target, testMethod);
Exception thrown = null;
try {
base.evaluate();
}
catch (Exception e) {
thrown = e;
}
finally {
getTestContextManager().afterTestMethod(target, testMethod, thrown);
}
}
};
}
private TestContextManager getTestContextManager() {
return testContextManager;
}
/**
* Creates a new {@link TestContextManager} for the supplied test class and the configured
* <em>default <code>ContextLoader</code> class name</em>. Can be overridden by subclasses.
*
* @param clazz the test class to be managed
* @see #getDefaultContextLoaderClassName(Class)
*/
protected TestContextManager createTestContextManager(Class<?> clazz) {
return new TestContextManager(clazz, getDefaultContextLoaderClassName(clazz));
}
/**
* Get the name of the default <code>ContextLoader</code> class to use for the supplied test class. The named class
* will be used if the test class does not explicitly declare a <code>ContextLoader</code> class via the
* <code>@ContextConfiguration</code> annotation.
* <p>
* The default implementation returns <code>null</code>, thus implying use of the <em>standard</em> default
* <code>ContextLoader</code> class name. Can be overridden by subclasses.
* </p>
*
* @param clazz the test class
* @return <code>null</code>
*/
protected String getDefaultContextLoaderClassName(Class<?> clazz) {
return null;
}
}