Introduce JUnit Rule alternative to SpringJUnit4ClassRunner
Since Spring Framework 2.5, support for integrating the Spring TestContext Framework (TCF) into JUnit 4 based tests has been provided via the SpringJUnit4ClassRunner, but this approach precludes the ability for tests to be run with alternative runners like JUnit's Parameterized or third-party runners such as the MockitoJUnitRunner. This commit remedies this situation by introducing @ClassRule and @Rule based alternatives to the SpringJUnit4ClassRunner. These rules are independent of any Runner and can therefore be combined with alternative runners. Due to the limitations of JUnit's implementation of rules, as of JUnit 4.12 it is currently impossible to create a single rule that can be applied both at the class level and at the method level (with access to the test instance). Consequently, this commit introduces the following two rules that must be used together. - SpringClassRule: a JUnit TestRule that provides the class-level functionality of the TCF to JUnit-based tests - SpringMethodRule: a JUnit MethodRule that provides the instance-level and method-level functionality of the TCF to JUnit-based tests In addition, this commit also introduces the following new JUnit Statements for use with rules: - RunPrepareTestInstanceCallbacks - ProfileValueChecker Issue: SPR-7731
This commit is contained in:
parent
49fff7513d
commit
d1b1c4f888
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.test.context.junit4;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -36,12 +37,12 @@ import org.springframework.test.context.web.ServletTestExecutionListener;
|
|||
* in a <strong>JUnit</strong> environment.
|
||||
*
|
||||
* <p>Concrete subclasses should typically declare a class-level
|
||||
* {@link ContextConfiguration @ContextConfiguration} annotation to
|
||||
* configure the {@link ApplicationContext application context} {@link
|
||||
* {@link ContextConfiguration @ContextConfiguration} annotation to
|
||||
* configure the {@linkplain ApplicationContext application context} {@link
|
||||
* ContextConfiguration#locations() resource locations} or {@link
|
||||
* ContextConfiguration#classes() annotated classes}. <em>If your test does not
|
||||
* need to load an application context, you may choose to omit the {@link
|
||||
* ContextConfiguration @ContextConfiguration} declaration and to configure
|
||||
* need to load an application context, you may choose to omit the
|
||||
* {@link ContextConfiguration @ContextConfiguration} declaration and to configure
|
||||
* the appropriate {@link org.springframework.test.context.TestExecutionListener
|
||||
* TestExecutionListeners} manually.</em>
|
||||
*
|
||||
|
@ -54,12 +55,18 @@ import org.springframework.test.context.web.ServletTestExecutionListener;
|
|||
* <li>{@link org.springframework.test.context.support.DirtiesContextTestExecutionListener}
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note: this class serves only as a convenience for extension. If you do not
|
||||
* wish for your test classes to be tied to a Spring-specific class hierarchy,
|
||||
* you may configure your own custom test classes by using
|
||||
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
|
||||
* @ContextConfiguration}, {@link TestExecutionListeners
|
||||
* @TestExecutionListeners}, etc.
|
||||
* <p>This class serves only as a convenience for extension.
|
||||
* <ul>
|
||||
* <li>If you do not wish for your test classes to be tied to a Spring-specific
|
||||
* class hierarchy, you may configure your own custom test classes by using
|
||||
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration @ContextConfiguration},
|
||||
* {@link TestExecutionListeners @TestExecutionListeners}, etc.</li>
|
||||
* <li>If you wish to extend this class and use a runner other than the
|
||||
* {@link SpringJUnit4ClassRunner}, as of Spring Framework 4.2 you can use
|
||||
* {@link org.springframework.test.context.junit4.rules.SpringClassRule SpringClassRule} and
|
||||
* {@link org.springframework.test.context.junit4.rules.SpringMethodRule SpringMethodRule}
|
||||
* and specify your runner of choice via {@link RunWith @RunWith(...)}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>NOTE:</strong> As of Spring Framework 4.1, this class requires JUnit 4.9 or higher.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -60,13 +60,18 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
* <li>{@link org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener}
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note: this class serves only as a convenience for extension. If you do not
|
||||
* wish for your test classes to be tied to a Spring-specific class hierarchy,
|
||||
* you may configure your own custom test classes by using
|
||||
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
|
||||
* @ContextConfiguration}, {@link TestExecutionListeners
|
||||
* @TestExecutionListeners}, {@link Transactional @Transactional},
|
||||
* etc.
|
||||
* <p>This class serves only as a convenience for extension.
|
||||
* <ul>
|
||||
* <li>If you do not wish for your test classes to be tied to a Spring-specific
|
||||
* class hierarchy, you may configure your own custom test classes by using
|
||||
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration @ContextConfiguration},
|
||||
* {@link TestExecutionListeners @TestExecutionListeners}, etc.</li>
|
||||
* <li>If you wish to extend this class and use a runner other than the
|
||||
* {@link SpringJUnit4ClassRunner}, as of Spring Framework 4.2 you can use
|
||||
* {@link org.springframework.test.context.junit4.rules.SpringClassRule SpringClassRule} and
|
||||
* {@link org.springframework.test.context.junit4.rules.SpringMethodRule SpringMethodRule}
|
||||
* and specify your runner of choice via {@link org.junit.runner.RunWith @RunWith(...)}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>NOTE:</strong> As of Spring Framework 4.1, this class requires JUnit 4.9 or higher.
|
||||
*
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -41,6 +42,8 @@ import org.springframework.test.annotation.ProfileValueUtils;
|
|||
import org.springframework.test.annotation.Repeat;
|
||||
import org.springframework.test.annotation.Timed;
|
||||
import org.springframework.test.context.TestContextManager;
|
||||
import org.springframework.test.context.junit4.rules.SpringClassRule;
|
||||
import org.springframework.test.context.junit4.rules.SpringMethodRule;
|
||||
import org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks;
|
||||
import org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks;
|
||||
import org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks;
|
||||
|
@ -72,6 +75,9 @@ import org.springframework.util.ReflectionUtils;
|
|||
* <li>{@link org.springframework.test.annotation.IfProfileValue @IfProfileValue}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>If you would like to use the Spring TestContext Framework with a runner
|
||||
* other than this one, use {@link SpringClassRule} and {@link SpringMethodRule}.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> As of Spring Framework 4.1, this class requires JUnit 4.9 or higher.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
|
@ -80,6 +86,8 @@ import org.springframework.util.ReflectionUtils;
|
|||
* @see TestContextManager
|
||||
* @see AbstractJUnit4SpringContextTests
|
||||
* @see AbstractTransactionalJUnit4SpringContextTests
|
||||
* @see org.springframework.test.context.junit4.rules.SpringClassRule
|
||||
* @see org.springframework.test.context.junit4.rules.SpringMethodRule
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
|
@ -101,6 +109,19 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
private final TestContextManager testContextManager;
|
||||
|
||||
|
||||
private static void ensureSpringRulesAreNotPresent(Class<?> testClass) {
|
||||
for (Field field : testClass.getFields()) {
|
||||
if (SpringClassRule.class.isAssignableFrom(field.getType())) {
|
||||
throw new IllegalStateException(String.format("Detected SpringClassRule field in test class [%s], but "
|
||||
+ "SpringClassRule cannot be used with the SpringJUnit4ClassRunner.", testClass.getName()));
|
||||
}
|
||||
if (SpringMethodRule.class.isAssignableFrom(field.getType())) {
|
||||
throw new IllegalStateException(String.format("Detected SpringMethodRule field in test class [%s], "
|
||||
+ "but SpringMethodRule cannot be used with the SpringJUnit4ClassRunner.", testClass.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code SpringJUnit4ClassRunner} and initialize a
|
||||
* {@link TestContextManager} to provide Spring testing functionality to
|
||||
|
@ -113,6 +134,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SpringJUnit4ClassRunner constructor called with [" + clazz + "].");
|
||||
}
|
||||
ensureSpringRulesAreNotPresent(clazz);
|
||||
this.testContextManager = createTestContextManager(clazz);
|
||||
}
|
||||
|
||||
|
@ -166,7 +188,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
|
||||
/**
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunBeforeTestClassCallbacks} statement, thus preserving the
|
||||
* {@code RunBeforeTestClassCallbacks} statement, thus preserving the
|
||||
* default JUnit functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunBeforeTestClassCallbacks
|
||||
|
@ -179,7 +201,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
|
||||
/**
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunAfterTestClassCallbacks} statement, thus preserving the default
|
||||
* {@code RunAfterTestClassCallbacks} statement, thus preserving the default
|
||||
* JUnit functionality while adding support for the Spring TestContext Framework.
|
||||
* @see RunAfterTestClassCallbacks
|
||||
*/
|
||||
|
@ -393,7 +415,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
|
||||
/**
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunBeforeTestMethodCallbacks} statement, thus preserving the
|
||||
* {@code RunBeforeTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunBeforeTestMethodCallbacks
|
||||
|
@ -407,7 +429,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
|
||||
/**
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunAfterTestMethodCallbacks} statement, thus preserving the
|
||||
* {@code RunAfterTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunAfterTestMethodCallbacks
|
||||
|
@ -423,10 +445,10 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
|||
* Return a {@link Statement} that potentially repeats the execution of
|
||||
* the {@code next} statement.
|
||||
* <p>Supports Spring's {@link Repeat @Repeat} annotation by returning a
|
||||
* {@link SpringRepeat} statement initialized with the configured repeat
|
||||
* {@code SpringRepeat} statement initialized with the configured repeat
|
||||
* count (if greater than {@code 1}); otherwise, the supplied statement
|
||||
* is returned unmodified.
|
||||
* @return either a {@link SpringRepeat} or the supplied {@link Statement}
|
||||
* @return either a {@code SpringRepeat} or the supplied {@code Statement}
|
||||
* as appropriate
|
||||
* @see SpringRepeat
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
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;
|
||||
|
||||
import org.springframework.test.context.TestContextManager;
|
||||
import org.springframework.test.context.junit4.statements.ProfileValueChecker;
|
||||
import org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks;
|
||||
import org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks;
|
||||
|
||||
/**
|
||||
* {@code SpringClassRule} is a custom JUnit {@link TestRule} that provides
|
||||
* <em>class-level</em> functionality of the <em>Spring TestContext Framework</em>
|
||||
* to standard JUnit tests by means of the {@link TestContextManager} and associated
|
||||
* support classes and annotations.
|
||||
*
|
||||
* <p>In contrast to the {@link org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
* SpringJUnit4ClassRunner}, Spring's rule-based JUnit support has the advantage
|
||||
* that it is independent of any {@link org.junit.runner.Runner Runner} and
|
||||
* can therefore be combined with existing alternative runners like JUnit's
|
||||
* {@code Parameterized} or third-party runners such as the {@code MockitoJUnitRunner}.
|
||||
*
|
||||
* <p>In order to achieve the same functionality as the {@code SpringJUnit4ClassRunner},
|
||||
* however, a {@code SpringClassRule} must be combined with a {@link SpringMethodRule},
|
||||
* since {@code SpringClassRule} only provides the class-level features of the
|
||||
* {@code SpringJUnit4ClassRunner}.
|
||||
*
|
||||
* <h3>Example Usage</h3>
|
||||
* <pre><code> public class ExampleSpringIntegrationTest {
|
||||
*
|
||||
* @ClassRule
|
||||
* public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
*
|
||||
* @Rule
|
||||
* public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
*
|
||||
* // ...
|
||||
* }</code></pre>
|
||||
*
|
||||
* <p>The following list constitutes all annotations currently supported directly
|
||||
* or indirectly by {@code SpringClassRule}. <em>(Note that additional annotations
|
||||
* may be supported by various
|
||||
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListener} or
|
||||
* {@link org.springframework.test.context.TestContextBootstrapper TestContextBootstrapper}
|
||||
* implementations.)</em>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.test.annotation.ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}</li>
|
||||
* <li>{@link org.springframework.test.annotation.IfProfileValue @IfProfileValue}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Philippe Marschall
|
||||
* @since 4.2
|
||||
* @see #apply(Statement, Description)
|
||||
* @see SpringMethodRule
|
||||
* @see org.springframework.test.context.TestContextManager
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
*/
|
||||
public class SpringClassRule implements TestRule {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpringClassRule.class);
|
||||
|
||||
/**
|
||||
* This field is {@code volatile} since a {@code SpringMethodRule} can
|
||||
* potentially access it from a different thread, depending on the type
|
||||
* of JUnit runner in use.
|
||||
*/
|
||||
private volatile TestContextManager testContextManager;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link TestContextManager} for the supplied test class.
|
||||
* <p>Can be overridden by subclasses.
|
||||
* @param clazz the test class to be managed
|
||||
*/
|
||||
protected TestContextManager createTestContextManager(Class<?> clazz) {
|
||||
return new TestContextManager(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link TestContextManager} associated with this rule.
|
||||
* <p>Will be {@code null} until the {@link #apply} method is invoked
|
||||
* by a JUnit runner.
|
||||
*/
|
||||
protected final TestContextManager getTestContextManager() {
|
||||
return this.testContextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply <em>class-level</em> functionality of the <em>Spring TestContext
|
||||
* Framework</em> to the supplied {@code base} statement.
|
||||
*
|
||||
* <p>Specifically, this method creates 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
|
||||
* functionality of the Spring TestContext Framework
|
||||
* @see #createTestContextManager
|
||||
* @see #withBeforeTestClassCallbacks
|
||||
* @see #withAfterTestClassCallbacks
|
||||
* @see #withProfileValueCheck
|
||||
*/
|
||||
@Override
|
||||
public Statement apply(final Statement base, final Description description) {
|
||||
Class<?> testClass = description.getTestClass();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Applying SpringClassRule to test class [" + testClass.getName() + "].");
|
||||
}
|
||||
|
||||
validateSpringMethodRuleConfiguration(testClass);
|
||||
|
||||
this.testContextManager = createTestContextManager(testClass);
|
||||
|
||||
Statement statement = base;
|
||||
statement = withBeforeTestClassCallbacks(statement);
|
||||
statement = withAfterTestClassCallbacks(statement);
|
||||
statement = withProfileValueCheck(testClass, statement);
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@code statement} with a {@code RunBeforeTestClassCallbacks} statement.
|
||||
* @see RunBeforeTestClassCallbacks
|
||||
*/
|
||||
protected Statement withBeforeTestClassCallbacks(Statement statement) {
|
||||
return new RunBeforeTestClassCallbacks(statement, getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@code statement} with a {@code RunAfterTestClassCallbacks} statement.
|
||||
* @see RunAfterTestClassCallbacks
|
||||
*/
|
||||
protected Statement withAfterTestClassCallbacks(Statement statement) {
|
||||
return new RunAfterTestClassCallbacks(statement, getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@code statement} with a {@code ProfileValueChecker} statement.
|
||||
* @see ProfileValueChecker
|
||||
*/
|
||||
protected Statement withProfileValueCheck(Class<?> testClass, Statement statement) {
|
||||
return new ProfileValueChecker(statement, testClass, null);
|
||||
}
|
||||
|
||||
private 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()))) {
|
||||
ruleField = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
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;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.test.annotation.Repeat;
|
||||
import org.springframework.test.annotation.Timed;
|
||||
import org.springframework.test.context.TestContextManager;
|
||||
import org.springframework.test.context.junit4.statements.ProfileValueChecker;
|
||||
import org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks;
|
||||
import org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks;
|
||||
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.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@code SpringMethodRule} is a custom JUnit {@link MethodRule} that
|
||||
* provides instance-level and method-level functionality of the
|
||||
* <em>Spring TestContext Framework</em> to standard JUnit tests by means
|
||||
* of the {@link TestContextManager} and associated support classes and
|
||||
* annotations.
|
||||
*
|
||||
* <p>In contrast to the {@link org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
* SpringJUnit4ClassRunner}, Spring's rule-based JUnit support has the advantage
|
||||
* that it is independent of any {@link org.junit.runner.Runner Runner} and
|
||||
* can therefore be combined with existing alternative runners like JUnit's
|
||||
* {@code Parameterized} or third-party runners such as the {@code MockitoJUnitRunner}.
|
||||
*
|
||||
* <p>In order to achieve the same functionality as the {@code SpringJUnit4ClassRunner},
|
||||
* however, a {@code SpringMethodRule} must be combined with a {@link SpringClassRule},
|
||||
* since {@code SpringMethodRule} only provides the method-level features of the
|
||||
* {@code SpringJUnit4ClassRunner}.
|
||||
*
|
||||
* <h3>Example Usage</h3>
|
||||
* <pre><code> public class ExampleSpringIntegrationTest {
|
||||
*
|
||||
* @ClassRule
|
||||
* public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
*
|
||||
* @Rule
|
||||
* public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
*
|
||||
* // ...
|
||||
* }</code></pre>
|
||||
*
|
||||
* <p>The following list constitutes all annotations currently supported directly
|
||||
* or indirectly by {@code SpringMethodRule}. <em>(Note that additional annotations
|
||||
* may be supported by various
|
||||
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListener} or
|
||||
* {@link org.springframework.test.context.TestContextBootstrapper TestContextBootstrapper}
|
||||
* implementations.)</em>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link Timed @Timed}</li>
|
||||
* <li>{@link Repeat @Repeat}</li>
|
||||
* <li>{@link org.springframework.test.annotation.ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}</li>
|
||||
* <li>{@link org.springframework.test.annotation.IfProfileValue @IfProfileValue}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Philippe Marschall
|
||||
* @since 4.2
|
||||
* @see #apply(Statement, FrameworkMethod, Object)
|
||||
* @see SpringClassRule
|
||||
* @see org.springframework.test.context.TestContextManager
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
*/
|
||||
public class SpringMethodRule implements MethodRule {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpringMethodRule.class);
|
||||
|
||||
/**
|
||||
* {@code SpringMethodRule} retains a reference to the {@code SpringClassRule}
|
||||
* instead of the {@code TestContextManager}, since the class rule <em>owns</em>
|
||||
* the {@code TestContextManager}.
|
||||
*/
|
||||
private final SpringClassRule springClassRule;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@code SpringMethodRule} for the supplied test instance.
|
||||
*
|
||||
* <p>The test class must declare a {@code public static final SpringClassRule}
|
||||
* field (i.e., a <em>constant</em>) that is annotated with JUnit's
|
||||
* {@link ClassRule @ClassRule} — for example:
|
||||
*
|
||||
* <pre><code> @ClassRule
|
||||
* public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();</code></pre>
|
||||
*
|
||||
* @param testInstance the test instance, never {@code null}
|
||||
* @throws IllegalStateException if the test class does not declare an
|
||||
* appropriate {@code SpringClassRule} constant.
|
||||
*/
|
||||
public SpringMethodRule(Object testInstance) {
|
||||
Assert.notNull(testInstance, "testInstance must not be null");
|
||||
this.springClassRule = retrieveAndValidateSpringClassRule(testInstance.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply <em>instance-level</em> and <em>method-level</em> functionality
|
||||
* 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
|
||||
* @return a statement that wraps the supplied {@code base} with instance-level
|
||||
* and method-level functionality of the Spring TestContext Framework
|
||||
* @see #withBeforeTestMethodCallbacks
|
||||
* @see #withAfterTestMethodCallbacks
|
||||
* @see #withPotentialRepeat
|
||||
* @see #withPotentialTimeout
|
||||
* @see #withTestInstancePreparation
|
||||
* @see #withProfileValueCheck
|
||||
*/
|
||||
@Override
|
||||
public Statement apply(final Statement base, final FrameworkMethod frameworkMethod, final Object testInstance) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Applying SpringMethodRule to test method [" + frameworkMethod.getMethod() + "].");
|
||||
}
|
||||
|
||||
Statement statement = base;
|
||||
statement = withBeforeTestMethodCallbacks(frameworkMethod, testInstance, statement);
|
||||
statement = withAfterTestMethodCallbacks(frameworkMethod, testInstance, statement);
|
||||
statement = withTestInstancePreparation(testInstance, statement);
|
||||
statement = withPotentialRepeat(frameworkMethod, testInstance, statement);
|
||||
statement = withPotentialTimeout(frameworkMethod, testInstance, statement);
|
||||
statement = withProfileValueCheck(frameworkMethod, testInstance, statement);
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link TestContextManager} associated with this rule.
|
||||
*/
|
||||
protected final TestContextManager getTestContextManager() {
|
||||
return this.springClassRule.getTestContextManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@link Statement} with a {@code ProfileValueChecker} statement.
|
||||
* @see ProfileValueChecker
|
||||
*/
|
||||
protected Statement withProfileValueCheck(FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
|
||||
return new ProfileValueChecker(statement, testInstance.getClass(), frameworkMethod.getMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@link Statement} with a {@code RunPrepareTestInstanceCallbacks} statement.
|
||||
* @see RunPrepareTestInstanceCallbacks
|
||||
*/
|
||||
protected Statement withTestInstancePreparation(Object testInstance, Statement statement) {
|
||||
return new RunPrepareTestInstanceCallbacks(statement, testInstance, getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@link Statement} with a {@code RunBeforeTestMethodCallbacks} statement.
|
||||
* @see RunBeforeTestMethodCallbacks
|
||||
*/
|
||||
protected Statement withBeforeTestMethodCallbacks(FrameworkMethod frameworkMethod, Object testInstance,
|
||||
Statement statement) {
|
||||
return new RunBeforeTestMethodCallbacks(statement, testInstance, frameworkMethod.getMethod(),
|
||||
getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the supplied {@link Statement} with a {@code RunAfterTestMethodCallbacks} statement.
|
||||
* @see RunAfterTestMethodCallbacks
|
||||
*/
|
||||
protected Statement withAfterTestMethodCallbacks(FrameworkMethod frameworkMethod, Object testInstance,
|
||||
Statement statement) {
|
||||
return new RunAfterTestMethodCallbacks(statement, testInstance, frameworkMethod.getMethod(),
|
||||
getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link Statement} that potentially repeats the execution of
|
||||
* the {@code next} statement.
|
||||
* <p>Supports Spring's {@link Repeat @Repeat} annotation by returning a
|
||||
* {@link SpringRepeat} statement initialized with the configured repeat
|
||||
* count (if greater than {@code 1}); otherwise, the supplied statement
|
||||
* is returned unmodified.
|
||||
* @return either a {@code SpringRepeat} or the supplied {@code Statement}
|
||||
* @see SpringRepeat
|
||||
*/
|
||||
protected Statement withPotentialRepeat(FrameworkMethod frameworkMethod, Object testInstance, Statement next) {
|
||||
Repeat repeatAnnotation = AnnotationUtils.getAnnotation(frameworkMethod.getMethod(), Repeat.class);
|
||||
int repeat = (repeatAnnotation != null ? repeatAnnotation.value() : 1);
|
||||
return (repeat > 1 ? new SpringRepeat(next, frameworkMethod.getMethod(), repeat) : next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link Statement} that potentially throws an exception if
|
||||
* the {@code next} statement in the execution chain takes longer than
|
||||
* a specified timeout.
|
||||
* <p>Supports Spring's {@link Timed @Timed} annotation by returning a
|
||||
* {@link SpringFailOnTimeout} statement initialized with the configured
|
||||
* timeout (if greater than {@code 0}); otherwise, the supplied statement
|
||||
* is returned unmodified.
|
||||
* @return either a {@code SpringFailOnTimeout} or the supplied {@code Statement}
|
||||
* @see #getSpringTimeout(FrameworkMethod)
|
||||
* @see SpringFailOnTimeout
|
||||
*/
|
||||
protected Statement withPotentialTimeout(FrameworkMethod frameworkMethod, Object testInstance, Statement next) {
|
||||
long springTimeout = getSpringTimeout(frameworkMethod);
|
||||
return (springTimeout > 0 ? new SpringFailOnTimeout(next, springTimeout) : next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the configured Spring-specific {@code timeout} from the
|
||||
* {@link Timed @Timed} annotation on the supplied
|
||||
* {@linkplain FrameworkMethod test method}.
|
||||
* @return the timeout, or {@code 0} if none was specified
|
||||
*/
|
||||
protected long getSpringTimeout(FrameworkMethod frameworkMethod) {
|
||||
AnnotationAttributes annAttrs = AnnotatedElementUtils.findAnnotationAttributes(frameworkMethod.getMethod(),
|
||||
Timed.class.getName());
|
||||
if (annAttrs == null) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
long millis = annAttrs.<Long> getNumber("millis").longValue();
|
||||
return millis > 0 ? millis : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static SpringClassRule retrieveAndValidateSpringClassRule(Class<?> testClass) {
|
||||
Field springClassRuleField = null;
|
||||
|
||||
for (Field field : testClass.getFields()) {
|
||||
if (ReflectionUtils.isPublicStaticFinal(field) && (SpringClassRule.class.isAssignableFrom(field.getType()))) {
|
||||
springClassRuleField = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (springClassRuleField == 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()));
|
||||
}
|
||||
|
||||
if (!springClassRuleField.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.", springClassRuleField));
|
||||
}
|
||||
|
||||
return (SpringClassRule) ReflectionUtils.getField(springClassRuleField, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Custom JUnit {@code Rules} used in the <em>Spring TestContext Framework</em>.
|
||||
*/
|
||||
package org.springframework.test.context.junit4.rules;
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.statements;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
import org.springframework.test.annotation.ProfileValueUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@code ProfileValueChecker} is a custom JUnit {@link Statement} that checks
|
||||
* whether a test class or test method is enabled in the current environment
|
||||
* via Spring's {@link IfProfileValue @IfProfileValue} annotation.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Philippe Marschall
|
||||
* @since 4.2
|
||||
* @see #evaluate()
|
||||
* @see IfProfileValue
|
||||
* @see ProfileValueUtils
|
||||
*/
|
||||
public class ProfileValueChecker extends Statement {
|
||||
|
||||
private final Statement next;
|
||||
|
||||
private final Class<?> testClass;
|
||||
|
||||
private final Method testMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@code ProfileValueChecker} statement.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public ProfileValueChecker(Statement next, Class<?> testClass, Method testMethod) {
|
||||
Assert.notNull(next, "The next statement must not be null");
|
||||
Assert.notNull(testClass, "The test class must not be null");
|
||||
this.next = next;
|
||||
this.testClass = testClass;
|
||||
this.testMethod = testMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the test specified by arguments to the
|
||||
* {@linkplain #ProfileValueChecker constructor} is <em>enabled</em> in
|
||||
* the current environment, as configured via the {@link IfProfileValue
|
||||
* @IfProfileValue} annotation.
|
||||
* <p>If the test is not annotated with {@code @IfProfileValue} it is
|
||||
* considered enabled.
|
||||
* <p>If a test is not enabled, this method will abort further evaluation
|
||||
* of the execution chain with a failed assumption; otherwise, this method
|
||||
* will simply evaluate the next {@link Statement} in the execution chain.
|
||||
* @see ProfileValueUtils#isTestEnabledInThisEnvironment(Class)
|
||||
* @see ProfileValueUtils#isTestEnabledInThisEnvironment(Method, Class)
|
||||
* @see org.junit.Assume
|
||||
*/
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
if (this.testMethod == null) {
|
||||
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(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 [%s] is not enabled in this environment for test class [%s].",
|
||||
AnnotationUtils.findAnnotation(testClass, IfProfileValue.class), testClass.getName()), false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(testMethod, 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);
|
||||
}
|
||||
}
|
||||
|
||||
this.next.evaluate();
|
||||
}
|
||||
|
||||
}
|
|
@ -25,13 +25,15 @@ import org.junit.runners.model.Statement;
|
|||
import org.springframework.test.context.TestContextManager;
|
||||
|
||||
/**
|
||||
* {@code RunAfterTestClassCallbacks} is a custom JUnit {@link Statement} which allows the
|
||||
* <em>Spring TestContext Framework</em> to be plugged into the JUnit execution chain by
|
||||
* calling {@link TestContextManager#afterTestClass() afterTestClass()} on the supplied
|
||||
* {@code RunAfterTestClassCallbacks} is a custom JUnit {@link Statement} which allows
|
||||
* the <em>Spring TestContext Framework</em> to be plugged into the JUnit execution chain
|
||||
* by calling {@link TestContextManager#afterTestClass afterTestClass()} on the supplied
|
||||
* {@link TestContextManager}.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
|
||||
*
|
||||
* @see #evaluate()
|
||||
* @see RunBeforeTestMethodCallbacks
|
||||
* @see RunBeforeTestClassCallbacks
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
|
|
|
@ -28,8 +28,10 @@ import org.springframework.test.context.TestContextManager;
|
|||
/**
|
||||
* {@code RunAfterTestMethodCallbacks} is a custom JUnit {@link Statement} which allows
|
||||
* the <em>Spring TestContext Framework</em> to be plugged into the JUnit execution chain
|
||||
* by calling {@link TestContextManager#afterTestMethod(Object, Method, Throwable)
|
||||
* afterTestMethod()} on the supplied {@link TestContextManager}.
|
||||
* by calling {@link TestContextManager#afterTestMethod afterTestMethod()} on the supplied
|
||||
* {@link TestContextManager}.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> This class requires JUnit 4.9 or higher.
|
||||
*
|
||||
* @see #evaluate()
|
||||
* @see RunBeforeTestMethodCallbacks
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.statements;
|
||||
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.test.context.TestContextManager;
|
||||
|
||||
/**
|
||||
* {@code RunPrepareTestInstanceCallbacks} is a custom JUnit {@link Statement} which
|
||||
* allows the <em>Spring TestContext Framework</em> to be plugged into the JUnit
|
||||
* execution chain by calling {@link TestContextManager#prepareTestInstance(Object)
|
||||
* prepareTestInstance()} on the supplied {@link TestContextManager}.
|
||||
*
|
||||
* @see #evaluate()
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class RunPrepareTestInstanceCallbacks extends Statement {
|
||||
|
||||
private final Statement next;
|
||||
|
||||
private final Object testInstance;
|
||||
|
||||
private final TestContextManager testContextManager;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@code prepareTestInstance()}; never {@code null}
|
||||
*/
|
||||
public RunPrepareTestInstanceCallbacks(Statement next, Object testInstance, TestContextManager testContextManager) {
|
||||
this.next = next;
|
||||
this.testInstance = testInstance;
|
||||
this.testContextManager = testContextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link TestContextManager#prepareTestInstance(Object)} and
|
||||
* then evaluate the next {@link Statement} in the execution chain
|
||||
* (typically an instance of {@link RunAfterTestMethodCallbacks}).
|
||||
*/
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
this.testContextManager.prepareTestInstance(testInstance);
|
||||
this.next.evaluate();
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,11 @@ import org.springframework.test.annotation.Timed;
|
|||
* if the next statement in the execution chain takes more than the specified
|
||||
* number of milliseconds.
|
||||
*
|
||||
* <p>In contrast to JUnit's
|
||||
* {@link org.junit.internal.runners.statements.FailOnTimeout FailOnTimeout},
|
||||
* 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
|
||||
|
@ -53,11 +58,9 @@ public class SpringFailOnTimeout extends Statement {
|
|||
|
||||
/**
|
||||
* Evaluate the next {@link Statement statement} in the execution chain
|
||||
* (typically an instance of
|
||||
* {@link org.junit.internal.runners.statements.InvokeMethod InvokeMethod}
|
||||
* or {@link org.junit.internal.runners.statements.ExpectException
|
||||
* ExpectException}) and throw a {@link TimeoutException} if the next
|
||||
* {@code statement} executes longer than the specified {@code timeout}.
|
||||
* (typically an instance of {@link SpringRepeat}) and throw a
|
||||
* {@link TimeoutException} if the next {@code statement} executes longer
|
||||
* than the specified {@code timeout}.
|
||||
*/
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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,8 +16,6 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +29,6 @@ import org.springframework.test.context.ContextConfiguration;
|
|||
* @see ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests
|
||||
* @see RelativePathSpringJUnit4ClassRunnerAppCtxTests
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { SpringJUnit4ClassRunnerAppCtxTests.DEFAULT_CONTEXT_RESOURCE_PATH }, inheritLocations = false)
|
||||
public class AbsolutePathSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests {
|
||||
/* all tests are in the parent class. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -19,10 +19,13 @@ package org.springframework.test.context.junit4;
|
|||
import javax.annotation.Resource;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
@ -56,6 +59,9 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio
|
|||
|
||||
protected boolean inTransaction = false;
|
||||
|
||||
@Rule
|
||||
public final TestName testName = new TestName();
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
|
@ -94,10 +100,21 @@ public class BeforeAndAfterTransactionAnnotationTests extends AbstractTransactio
|
|||
|
||||
@Before
|
||||
public void before() {
|
||||
assertShouldBeInTransaction();
|
||||
assertEquals("Verifying the number of rows in the person table before a test method.", (this.inTransaction ? 1
|
||||
: 0), countRowsInPersonTable(jdbcTemplate));
|
||||
}
|
||||
|
||||
private void assertShouldBeInTransaction() {
|
||||
boolean shouldBeInTransaction = !testName.getMethodName().equals("nonTransactionalMethod");
|
||||
assertInTransaction(shouldBeInTransaction);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
assertShouldBeInTransaction();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void transactionalMethod1() {
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
|
@ -33,7 +31,6 @@ import org.springframework.util.ResourceUtils;
|
|||
* @see AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
|
||||
* @see RelativePathSpringJUnit4ClassRunnerAppCtxTests
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_CONTEXT_RESOURCE_PATH })
|
||||
public class ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests {
|
||||
|
||||
|
|
|
@ -43,23 +43,19 @@ public class ExpectedExceptionSpringRunnerTests {
|
|||
|
||||
@Test
|
||||
public void expectedExceptions() throws Exception {
|
||||
Class<ExpectedExceptionSpringRunnerTestCase> testClass = ExpectedExceptionSpringRunnerTestCase.class;
|
||||
Class<?> testClass = ExpectedExceptionSpringRunnerTestCase.class;
|
||||
TrackingRunListener listener = new TrackingRunListener();
|
||||
RunNotifier notifier = new RunNotifier();
|
||||
notifier.addListener(listener);
|
||||
|
||||
new SpringJUnit4ClassRunner(testClass).run(notifier);
|
||||
assertEquals("Verifying number of failures for test class [" + testClass + "].", 0,
|
||||
listener.getTestFailureCount());
|
||||
assertEquals("Verifying number of tests started for test class [" + testClass + "].", 1,
|
||||
listener.getTestStartedCount());
|
||||
assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 1,
|
||||
listener.getTestFinishedCount());
|
||||
assertEquals("failures for test class [" + testClass + "].", 0, listener.getTestFailureCount());
|
||||
assertEquals("tests started for test class [" + testClass + "].", 1, listener.getTestStartedCount());
|
||||
assertEquals("tests finished for test class [" + testClass + "].", 1, listener.getTestFinishedCount());
|
||||
}
|
||||
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@TestExecutionListeners({})
|
||||
public static final class ExpectedExceptionSpringRunnerTestCase {
|
||||
|
||||
|
|
|
@ -16,16 +16,17 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestExecutionListener;
|
||||
|
@ -33,30 +34,26 @@ import org.springframework.test.context.TestExecutionListeners;
|
|||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* JUnit 4 based integration test for verifying that '<i>before</i>' and '<i>after</i>'
|
||||
* methods of {@link TestExecutionListener TestExecutionListeners} as well as
|
||||
* {@link BeforeTransaction @BeforeTransaction} and
|
||||
* {@link AfterTransaction @AfterTransaction} methods can fail a test in a
|
||||
* JUnit 4.4 environment, as requested in <a
|
||||
* href="http://opensource.atlassian.com/projects/spring/browse/SPR-3960"
|
||||
* target="_blank">SPR-3960</a>.
|
||||
* </p>
|
||||
* <p>
|
||||
* Indirectly, this class also verifies that all {@link TestExecutionListener}
|
||||
* JUnit environment, as requested in
|
||||
* <a href="https://jira.spring.io/browse/SPR-3960" target="_blank">SPR-3960</a>.
|
||||
*
|
||||
* <p>Indirectly, this class also verifies that all {@link TestExecutionListener}
|
||||
* lifecycle callbacks are called.
|
||||
* </p>
|
||||
* <p>
|
||||
* As of Spring 3.0, this class also tests support for the new
|
||||
*
|
||||
* <p>As of Spring 3.0, this class also tests support for the new
|
||||
* {@link TestExecutionListener#beforeTestClass(TestContext) beforeTestClass()}
|
||||
* and {@link TestExecutionListener#afterTestClass(TestContext)
|
||||
* afterTestClass()} lifecycle callback methods.
|
||||
* </p>
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 2.5
|
||||
|
@ -68,38 +65,42 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Collection<Object[]> testData() {
|
||||
return Arrays.asList(new Object[][] {//
|
||||
//
|
||||
{ AlwaysFailingBeforeTestClassTestCase.class.getSimpleName() },//
|
||||
{ AlwaysFailingAfterTestClassTestCase.class.getSimpleName() },//
|
||||
{ AlwaysFailingPrepareTestInstanceTestCase.class.getSimpleName() },//
|
||||
{ AlwaysFailingBeforeTestMethodTestCase.class.getSimpleName() },//
|
||||
{ AlwaysFailingAfterTestMethodTestCase.class.getSimpleName() },//
|
||||
{ FailingBeforeTransactionTestCase.class.getSimpleName() },//
|
||||
{ FailingAfterTransactionTestCase.class.getSimpleName() } //
|
||||
});
|
||||
public static Object[] testData() {
|
||||
return new Object[] {//
|
||||
AlwaysFailingBeforeTestClassTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingAfterTestClassTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingPrepareTestInstanceTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingBeforeTestMethodTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingAfterTestMethodTestCase.class.getSimpleName(),//
|
||||
FailingBeforeTransactionTestCase.class.getSimpleName(),//
|
||||
FailingAfterTransactionTestCase.class.getSimpleName() //
|
||||
};
|
||||
}
|
||||
|
||||
public FailingBeforeAndAfterMethodsJUnitTests(String testClassName) throws Exception {
|
||||
this.clazz = ClassUtils.forName(getClass().getName() + "." + testClassName, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
protected Runner getRunner(Class<?> testClass) throws Exception {
|
||||
Class<? extends Runner> runnerClass = testClass.getAnnotation(RunWith.class).value();
|
||||
Constructor<?> constructor = runnerClass.getConstructor(Class.class);
|
||||
return (Runner) BeanUtils.instantiateClass(constructor, testClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runTestAndAssertCounters() throws Exception {
|
||||
final TrackingRunListener listener = new TrackingRunListener();
|
||||
final RunNotifier notifier = new RunNotifier();
|
||||
TrackingRunListener listener = new TrackingRunListener();
|
||||
RunNotifier notifier = new RunNotifier();
|
||||
notifier.addListener(listener);
|
||||
|
||||
new SpringJUnit4ClassRunner(this.clazz).run(notifier);
|
||||
assertEquals("Verifying number of failures for test class [" + this.clazz + "].", 1,
|
||||
listener.getTestFailureCount());
|
||||
getRunner(this.clazz).run(notifier);
|
||||
assertEquals("Failures for test class [" + this.clazz + "].", 1, listener.getTestFailureCount());
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
static class AlwaysFailingBeforeTestClassTestExecutionListener extends AbstractTestExecutionListener {
|
||||
protected static class AlwaysFailingBeforeTestClassTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void beforeTestClass(TestContext testContext) {
|
||||
|
@ -107,7 +108,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class AlwaysFailingAfterTestClassTestExecutionListener extends AbstractTestExecutionListener {
|
||||
protected static class AlwaysFailingAfterTestClassTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void afterTestClass(TestContext testContext) {
|
||||
|
@ -115,7 +116,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class AlwaysFailingPrepareTestInstanceTestExecutionListener extends AbstractTestExecutionListener {
|
||||
protected static class AlwaysFailingPrepareTestInstanceTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void prepareTestInstance(TestContext testContext) throws Exception {
|
||||
|
@ -123,7 +124,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class AlwaysFailingBeforeTestMethodTestExecutionListener extends AbstractTestExecutionListener {
|
||||
protected static class AlwaysFailingBeforeTestMethodTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void beforeTestMethod(TestContext testContext) {
|
||||
|
@ -131,7 +132,7 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class AlwaysFailingAfterTestMethodTestExecutionListener extends AbstractTestExecutionListener {
|
||||
protected static class AlwaysFailingAfterTestMethodTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void afterTestMethod(TestContext testContext) {
|
||||
|
@ -174,8 +175,10 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("FailingBeforeAndAfterMethodsTests-context.xml")
|
||||
public static class FailingBeforeTransactionTestCase extends AbstractTransactionalJUnit4SpringContextTests {
|
||||
@Transactional
|
||||
public static class FailingBeforeTransactionTestCase {
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
|
@ -188,8 +191,10 @@ public class FailingBeforeAndAfterMethodsJUnitTests {
|
|||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("FailingBeforeAndAfterMethodsTests-context.xml")
|
||||
public static class FailingAfterTransactionTestCase extends AbstractTransactionalJUnit4SpringContextTests {
|
||||
@Transactional
|
||||
public static class FailingAfterTransactionTestCase {
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,8 +16,6 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
|
@ -36,7 +34,6 @@ import org.springframework.util.ResourceUtils;
|
|||
* @since 2.5
|
||||
* @see SpringJUnit4ClassRunnerAppCtxTests
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration( { MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_RESOURCE_PATH,
|
||||
MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.LOCAL_RESOURCE_PATH,
|
||||
MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.ABSOLUTE_RESOURCE_PATH })
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
|
@ -51,15 +48,16 @@ import static org.junit.Assert.*;
|
|||
*
|
||||
* @author Sam Brannen
|
||||
* @since 2.5
|
||||
* @see org.springframework.test.context.junit4.rules.ParameterizedSpringRuleTests
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
@ContextConfiguration
|
||||
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })
|
||||
public class ParameterizedDependencyInjectionTests {
|
||||
|
||||
private static final List<Employee> employees = new ArrayList<Employee>();
|
||||
private static final AtomicInteger invocationCount = new AtomicInteger();
|
||||
|
||||
private final TestContextManager testContextManager = new TestContextManager(getClass());
|
||||
private static final TestContextManager testContextManager = new TestContextManager(ParameterizedDependencyInjectionTests.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
@ -75,37 +73,37 @@ public class ParameterizedDependencyInjectionTests {
|
|||
|
||||
|
||||
@Parameters(name = "bean [{0}], employee [{1}]")
|
||||
public static Collection<String[]> employeeData() {
|
||||
return Arrays.asList(new String[][] { { "employee1", "John Smith" }, { "employee2", "Jane Smith" } });
|
||||
public static String[][] employeeData() {
|
||||
return new String[][] { { "employee1", "John Smith" }, { "employee2", "Jane Smith" } };
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void clearEmployees() {
|
||||
employees.clear();
|
||||
public static void BeforeClass() {
|
||||
invocationCount.set(0);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void injectDependencies() throws Throwable {
|
||||
this.testContextManager.prepareTestInstance(this);
|
||||
public void injectDependencies() throws Exception {
|
||||
testContextManager.prepareTestInstance(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void verifyPetAndEmployee() {
|
||||
invocationCount.incrementAndGet();
|
||||
|
||||
// Verifying dependency injection:
|
||||
assertNotNull("The pet field should have been autowired.", this.pet);
|
||||
|
||||
// Verifying 'parameterized' support:
|
||||
final Employee employee = (Employee) this.applicationContext.getBean(this.employeeBeanName);
|
||||
employees.add(employee);
|
||||
assertEquals("Verifying the name of the employee configured as bean [" + this.employeeBeanName + "].",
|
||||
this.employeeName, employee.getName());
|
||||
Employee employee = this.applicationContext.getBean(this.employeeBeanName, Employee.class);
|
||||
assertEquals("Name of the employee configured as bean [" + this.employeeBeanName + "].", this.employeeName,
|
||||
employee.getName());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void verifyNumParameterizedRuns() {
|
||||
assertEquals("Verifying the number of times the parameterized test method was executed.",
|
||||
employeeData().size(), employees.size());
|
||||
assertEquals("Number of times the parameterized test method was executed.", employeeData().length,
|
||||
invocationCount.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.springframework.test.context.junit4;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -30,7 +28,6 @@ import org.springframework.test.context.ContextConfiguration;
|
|||
* @see SpringJUnit4ClassRunnerAppCtxTests
|
||||
* @see AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "SpringJUnit4ClassRunnerAppCtxTests-context.xml" })
|
||||
public class RelativePathSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests {
|
||||
/* all tests are in the parent class. */
|
||||
|
|
|
@ -19,13 +19,12 @@ package org.springframework.test.context.junit4;
|
|||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
@ -41,8 +40,8 @@ import static org.junit.Assert.*;
|
|||
* Verifies proper handling of the following in conjunction with the
|
||||
* {@link SpringJUnit4ClassRunner}:
|
||||
* <ul>
|
||||
* <li>Spring's {@link Repeat @Repeat}</li>
|
||||
* <li>Spring's {@link Timed @Timed}</li>
|
||||
* <li>Spring's {@link Repeat @Repeat}</li>
|
||||
* <li>Spring's {@link Timed @Timed}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Sam Brannen
|
||||
|
@ -51,22 +50,19 @@ import static org.junit.Assert.*;
|
|||
@RunWith(Parameterized.class)
|
||||
public class RepeatedSpringRunnerTests {
|
||||
|
||||
private static final AtomicInteger invocationCount = new AtomicInteger();
|
||||
protected static final AtomicInteger invocationCount = new AtomicInteger();
|
||||
|
||||
private final Class<?> testClass;
|
||||
|
||||
private final int expectedFailureCount;
|
||||
|
||||
private final int expectedTestStartedCount;
|
||||
|
||||
private final int expectedTestFinishedCount;
|
||||
|
||||
private final int expectedInvocationCount;
|
||||
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Collection<Object[]> repetitionData() {
|
||||
return Arrays.asList(new Object[][] {//
|
||||
public static Object[][] repetitionData() {
|
||||
return new Object[][] {//
|
||||
//
|
||||
{ NonAnnotatedRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 1 },//
|
||||
{ DefaultRepeatValueRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 1 },//
|
||||
|
@ -74,7 +70,7 @@ public class RepeatedSpringRunnerTests {
|
|||
{ RepeatedFiveTimesRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 5 },//
|
||||
{ RepeatedFiveTimesViaMetaAnnotationRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 5 },//
|
||||
{ TimedRepeatedTestCase.class.getSimpleName(), 3, 4, 4, (5 + 1 + 4 + 10) } //
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public RepeatedSpringRunnerTests(String testClassName, int expectedFailureCount,
|
||||
|
@ -86,6 +82,10 @@ public class RepeatedSpringRunnerTests {
|
|||
this.expectedInvocationCount = expectedInvocationCount;
|
||||
}
|
||||
|
||||
protected Runner getRunner(Class<?> testClass) throws Exception {
|
||||
return new SpringJUnit4ClassRunner(testClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertRepetitions() throws Exception {
|
||||
TrackingRunListener listener = new TrackingRunListener();
|
||||
|
@ -93,19 +93,14 @@ public class RepeatedSpringRunnerTests {
|
|||
notifier.addListener(listener);
|
||||
invocationCount.set(0);
|
||||
|
||||
new SpringJUnit4ClassRunner(this.testClass).run(notifier);
|
||||
assertEquals("Verifying number of failures for test class [" + this.testClass + "].",
|
||||
this.expectedFailureCount, listener.getTestFailureCount());
|
||||
assertEquals("Verifying number of tests started for test class [" + this.testClass + "].",
|
||||
this.expectedTestStartedCount, listener.getTestStartedCount());
|
||||
assertEquals("Verifying number of tests finished for test class [" + this.testClass + "].",
|
||||
this.expectedTestFinishedCount, listener.getTestFinishedCount());
|
||||
assertEquals("Verifying number of invocations for test class [" + this.testClass + "].",
|
||||
this.expectedInvocationCount, invocationCount.get());
|
||||
getRunner(this.testClass).run(notifier);
|
||||
assertEquals("failures for [" + testClass + "].", expectedFailureCount, listener.getTestFailureCount());
|
||||
assertEquals("tests started for [" + testClass + "].", expectedTestStartedCount, listener.getTestStartedCount());
|
||||
assertEquals("tests finished for [" + testClass + "].", expectedTestFinishedCount, listener.getTestFinishedCount());
|
||||
assertEquals("invocations for [" + testClass + "].", expectedInvocationCount, invocationCount.get());
|
||||
}
|
||||
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@TestExecutionListeners({})
|
||||
public abstract static class AbstractRepeatedTestCase {
|
||||
|
||||
|
@ -167,9 +162,7 @@ public class RepeatedSpringRunnerTests {
|
|||
}
|
||||
|
||||
/**
|
||||
* Unit tests for claims raised in <a
|
||||
* href="http://jira.springframework.org/browse/SPR-6011"
|
||||
* target="_blank">SPR-6011</a>.
|
||||
* Unit tests for claims raised in <a href="https://jira.spring.io/browse/SPR-6011" target="_blank">SPR-6011</a>.
|
||||
*/
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
public static final class TimedRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.runners.Suite;
|
|||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.springframework.test.context.cache.ClassLevelDirtiesContextTests;
|
||||
import org.springframework.test.context.cache.SpringRunnerContextCacheTests;
|
||||
import org.springframework.test.context.jdbc.RequiresNewTransactionSqlScriptsTests;
|
||||
import org.springframework.test.context.junit4.annotation.AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests;
|
||||
import org.springframework.test.context.junit4.annotation.BeanOverridingDefaultConfigClassesInheritedTests;
|
||||
import org.springframework.test.context.junit4.annotation.BeanOverridingExplicitConfigClassesInheritedTests;
|
||||
|
@ -41,6 +42,7 @@ import org.springframework.test.context.junit4.profile.annotation.DevProfileReso
|
|||
import org.springframework.test.context.junit4.profile.xml.DefaultProfileXmlConfigTests;
|
||||
import org.springframework.test.context.junit4.profile.xml.DevProfileResolverXmlConfigTests;
|
||||
import org.springframework.test.context.junit4.profile.xml.DevProfileXmlConfigTests;
|
||||
import org.springframework.test.context.transaction.programmatic.ProgrammaticTxMgmtTests;
|
||||
|
||||
/**
|
||||
* JUnit test suite for tests involving {@link SpringJUnit4ClassRunner} and the
|
||||
|
@ -99,6 +101,7 @@ StandardJUnit4FeaturesTests.class,//
|
|||
SpringRunnerContextCacheTests.class,//
|
||||
ClassLevelDirtiesContextTests.class,//
|
||||
ParameterizedDependencyInjectionTests.class,//
|
||||
ConcreteTransactionalJUnit4SpringContextTests.class,//
|
||||
ClassLevelTransactionalSpringRunnerTests.class,//
|
||||
MethodLevelTransactionalSpringRunnerTests.class,//
|
||||
DefaultRollbackTrueTransactionalSpringRunnerTests.class,//
|
||||
|
@ -107,6 +110,8 @@ StandardJUnit4FeaturesTests.class,//
|
|||
RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class,//
|
||||
BeforeAndAfterTransactionAnnotationTests.class,//
|
||||
TimedTransactionalSpringRunnerTests.class,//
|
||||
ProgrammaticTxMgmtTests.class,//
|
||||
RequiresNewTransactionSqlScriptsTests.class,//
|
||||
HibernateSessionFlushingTests.class //
|
||||
})
|
||||
public class SpringJUnit4TestSuite {
|
||||
|
|
|
@ -22,13 +22,12 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runner.notification.RunNotifier;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.annotation.Timed;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
@ -46,32 +45,33 @@ import static org.junit.Assert.*;
|
|||
@RunWith(JUnit4.class)
|
||||
public class TimedSpringRunnerTests {
|
||||
|
||||
protected Class<?> getTestCase() {
|
||||
return TimedSpringRunnerTestCase.class;
|
||||
}
|
||||
|
||||
protected Runner getRunner(Class<?> testClass) throws Exception {
|
||||
return new SpringJUnit4ClassRunner(testClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timedTests() throws Exception {
|
||||
Assume.group(TestGroup.PERFORMANCE);
|
||||
Class<TimedSpringRunnerTestCase> testClass = TimedSpringRunnerTestCase.class;
|
||||
Class<?> testClass = getTestCase();
|
||||
TrackingRunListener listener = new TrackingRunListener();
|
||||
RunNotifier notifier = new RunNotifier();
|
||||
notifier.addListener(listener);
|
||||
|
||||
new SpringJUnit4ClassRunner(testClass).run(notifier);
|
||||
assertEquals("Verifying number of tests started for test class [" + testClass + "].", 7,
|
||||
listener.getTestStartedCount());
|
||||
assertEquals("Verifying number of tests ignored for test class [" + testClass + "].", 0,
|
||||
listener.getTestIgnoredCount());
|
||||
assertEquals("Verifying number of assumption failures for test class [" + testClass + "].", 0,
|
||||
listener.getTestAssumptionFailureCount());
|
||||
assertEquals("Verifying number of test failures for test class [" + testClass + "].", 5,
|
||||
listener.getTestFailureCount());
|
||||
assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 7,
|
||||
listener.getTestFinishedCount());
|
||||
getRunner(testClass).run(notifier);
|
||||
assertEquals("tests started for [" + testClass + "].", 7, listener.getTestStartedCount());
|
||||
assertEquals("tests ignored for [" + testClass + "].", 0, listener.getTestIgnoredCount());
|
||||
assertEquals("assumption failures for [" + testClass + "].", 0, listener.getTestAssumptionFailureCount());
|
||||
assertEquals("test failures for [" + testClass + "].", 5, listener.getTestFailureCount());
|
||||
assertEquals("tests finished for [" + testClass + "].", 7, listener.getTestFinishedCount());
|
||||
}
|
||||
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@TestExecutionListeners({})
|
||||
public static final class TimedSpringRunnerTestCase {
|
||||
public static class TimedSpringRunnerTestCase {
|
||||
|
||||
// Should Pass.
|
||||
@Test(timeout = 2000)
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Base class for integration tests involving Spring {@code ApplicationContexts}
|
||||
* in conjunction with {@link SpringClassRule} and {@link SpringMethodRule}.
|
||||
*
|
||||
* <p>The goal of this class and its subclasses is to ensure that Rule-based
|
||||
* configuration can be inherited without requiring {@link SpringClassRule}
|
||||
* or {@link SpringMethodRule} to be redeclared on subclasses.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see Subclass1AppCtxRuleTests
|
||||
* @see Subclass2AppCtxRuleTests
|
||||
*/
|
||||
@ContextConfiguration
|
||||
public class BaseAppCtxRuleTests {
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public String foo() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
@Autowired
|
||||
String foo;
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertEquals("foo", foo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.context.web.BasicAnnotationConfigWacTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link BasicAnnotationConfigWacTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class BasicAnnotationConfigWacSpringRuleTests extends BasicAnnotationConfigWacTests {
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.context.junit4.BeforeAndAfterTransactionAnnotationTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link BeforeAndAfterTransactionAnnotationTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class BeforeAndAfterTransactionAnnotationSpringRuleTests extends BeforeAndAfterTransactionAnnotationTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.context.junit4.ClassLevelDisabledSpringRunnerTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link ClassLevelDisabledSpringRunnerTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class ClassLevelDisabledSpringRuleTests extends ClassLevelDisabledSpringRunnerTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.context.junit4.EnabledAndIgnoredSpringRunnerTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link EnabledAndIgnoredSpringRunnerTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class EnabledAndIgnoredSpringRuleTests extends EnabledAndIgnoredSpringRunnerTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.FailingBeforeAndAfterMethodsJUnitTests;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link FailingBeforeAndAfterMethodsJUnitTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class FailingBeforeAndAfterMethodsSpringRuleTests extends FailingBeforeAndAfterMethodsJUnitTests {
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Object[] testData() {
|
||||
return new Object[] {//
|
||||
AlwaysFailingBeforeTestClassSpringRuleTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingAfterTestClassSpringRuleTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingPrepareTestInstanceSpringRuleTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingBeforeTestMethodSpringRuleTestCase.class.getSimpleName(),//
|
||||
AlwaysFailingAfterTestMethodSpringRuleTestCase.class.getSimpleName(),//
|
||||
FailingBeforeTransactionSpringRuleTestCase.class.getSimpleName(),//
|
||||
FailingAfterTransactionSpringRuleTestCase.class.getSimpleName() //
|
||||
};
|
||||
}
|
||||
|
||||
public FailingBeforeAndAfterMethodsSpringRuleTests(String testClassName) throws Exception {
|
||||
super(testClassName);
|
||||
}
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
@TestExecutionListeners({})
|
||||
public static abstract class BaseSpringRuleTestCase {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners(AlwaysFailingBeforeTestClassTestExecutionListener.class)
|
||||
public static class AlwaysFailingBeforeTestClassSpringRuleTestCase extends BaseSpringRuleTestCase {
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners(AlwaysFailingAfterTestClassTestExecutionListener.class)
|
||||
public static class AlwaysFailingAfterTestClassSpringRuleTestCase extends BaseSpringRuleTestCase {
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners(AlwaysFailingPrepareTestInstanceTestExecutionListener.class)
|
||||
public static class AlwaysFailingPrepareTestInstanceSpringRuleTestCase extends BaseSpringRuleTestCase {
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners(AlwaysFailingBeforeTestMethodTestExecutionListener.class)
|
||||
public static class AlwaysFailingBeforeTestMethodSpringRuleTestCase extends BaseSpringRuleTestCase {
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners(AlwaysFailingAfterTestMethodTestExecutionListener.class)
|
||||
public static class AlwaysFailingAfterTestMethodSpringRuleTestCase extends BaseSpringRuleTestCase {
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(JUnit4.class)
|
||||
@ContextConfiguration("../FailingBeforeAndAfterMethodsTests-context.xml")
|
||||
@Transactional
|
||||
public static class FailingBeforeTransactionSpringRuleTestCase {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void beforeTransaction() {
|
||||
fail("always failing beforeTransaction()");
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@RunWith(JUnit4.class)
|
||||
@ContextConfiguration("../FailingBeforeAndAfterMethodsTests-context.xml")
|
||||
@Transactional
|
||||
public static class FailingAfterTransactionSpringRuleTestCase {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
}
|
||||
|
||||
@AfterTransaction
|
||||
public void afterTransaction() {
|
||||
fail("always failing afterTransaction()");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.tests.sample.beans.Employee;
|
||||
import org.springframework.tests.sample.beans.Pet;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration test which demonstrates how to use JUnit's {@link Parameterized}
|
||||
* runner in conjunction with {@link SpringClassRule} and {@link SpringMethodRule}
|
||||
* to provide dependency injection to a <em>parameterized test instance</em>.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see org.springframework.test.context.junit4.ParameterizedDependencyInjectionTests
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
@ContextConfiguration("/org/springframework/test/context/junit4/ParameterizedDependencyInjectionTests-context.xml")
|
||||
public class ParameterizedSpringRuleTests {
|
||||
|
||||
private static final AtomicInteger invocationCount = new AtomicInteger();
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private Pet pet;
|
||||
|
||||
@Parameter(0)
|
||||
public String employeeBeanName;
|
||||
|
||||
@Parameter(1)
|
||||
public String employeeName;
|
||||
|
||||
|
||||
@Parameters(name = "bean [{0}], employee [{1}]")
|
||||
public static String[][] employeeData() {
|
||||
return new String[][] { { "employee1", "John Smith" }, { "employee2", "Jane Smith" } };
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void BeforeClass() {
|
||||
invocationCount.set(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void verifyPetAndEmployee() {
|
||||
invocationCount.incrementAndGet();
|
||||
|
||||
// Verifying dependency injection:
|
||||
assertNotNull("The pet field should have been autowired.", this.pet);
|
||||
|
||||
// Verifying 'parameterized' support:
|
||||
Employee employee = this.applicationContext.getBean(this.employeeBeanName, Employee.class);
|
||||
assertEquals("Name of the employee configured as bean [" + this.employeeBeanName + "].", this.employeeName,
|
||||
employee.getName());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void verifyNumParameterizedRuns() {
|
||||
assertEquals("Number of times the parameterized test method was executed.", employeeData().length,
|
||||
invocationCount.get());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.transaction.programmatic.ProgrammaticTxMgmtTests;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link ProgrammaticTxMgmtTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
@ContextConfiguration
|
||||
public class ProgrammaticTxMgmtSpringRuleTests extends ProgrammaticTxMgmtTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new DataSourceTransactionManager(dataSource());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()//
|
||||
.generateUniqueName(true)//
|
||||
.addScript("classpath:/org/springframework/test/context/jdbc/schema.sql") //
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.test.annotation.Repeat;
|
||||
import org.springframework.test.annotation.Timed;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.RepeatedSpringRunnerTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link RepeatedSpringRunnerTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class RepeatedSpringRuleTests extends RepeatedSpringRunnerTests {
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Object[][] repetitionData() {
|
||||
return new Object[][] {//
|
||||
//
|
||||
{ NonAnnotatedRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 1 },//
|
||||
{ DefaultRepeatValueRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 1 },//
|
||||
{ NegativeRepeatValueRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 1 },//
|
||||
{ RepeatedFiveTimesRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 5 },//
|
||||
{ RepeatedFiveTimesViaMetaAnnotationRepeatedTestCase.class.getSimpleName(), 0, 1, 1, 5 },//
|
||||
{ TimedRepeatedTestCase.class.getSimpleName(), 3, 4, 4, (5 + 1 + 4 + 10) } //
|
||||
};
|
||||
}
|
||||
|
||||
public RepeatedSpringRuleTests(String testClassName, int expectedFailureCount, int expectedTestStartedCount,
|
||||
int expectedTestFinishedCount, int expectedInvocationCount) throws Exception {
|
||||
|
||||
super(testClassName, expectedFailureCount, expectedTestStartedCount, expectedTestFinishedCount,
|
||||
expectedInvocationCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Runner getRunner(Class<?> testClass) throws Exception {
|
||||
return new JUnit4(testClass);
|
||||
}
|
||||
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
@TestExecutionListeners({})
|
||||
public abstract static class AbstractRepeatedTestCase {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
|
||||
protected void incrementInvocationCount() throws IOException {
|
||||
invocationCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NonAnnotatedRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@Timed(millis = 10000)
|
||||
public void nonAnnotated() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DefaultRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@Repeat
|
||||
@Timed(millis = 10000)
|
||||
public void defaultRepeatValue() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NegativeRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@Repeat(-5)
|
||||
@Timed(millis = 10000)
|
||||
public void negativeRepeatValue() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class RepeatedFiveTimesRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@Repeat(5)
|
||||
public void repeatedFiveTimes() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Repeat(5)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private static @interface RepeatedFiveTimes {
|
||||
}
|
||||
|
||||
public static final class RepeatedFiveTimesViaMetaAnnotationRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@RepeatedFiveTimes
|
||||
public void repeatedFiveTimes() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit tests for claims raised in <a href="https://jira.spring.io/browse/SPR-6011" target="_blank">SPR-6011</a>.
|
||||
*/
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
public static final class TimedRepeatedTestCase extends AbstractRepeatedTestCase {
|
||||
|
||||
@Test
|
||||
@Timed(millis = 1000)
|
||||
@Repeat(5)
|
||||
public void repeatedFiveTimesButDoesNotExceedTimeout() throws Exception {
|
||||
incrementInvocationCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timed(millis = 10)
|
||||
@Repeat(1)
|
||||
public void singleRepetitionExceedsTimeout() throws Exception {
|
||||
incrementInvocationCount();
|
||||
Thread.sleep(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timed(millis = 20)
|
||||
@Repeat(4)
|
||||
public void firstRepetitionOfManyExceedsTimeout() throws Exception {
|
||||
incrementInvocationCount();
|
||||
Thread.sleep(25);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timed(millis = 100)
|
||||
@Repeat(10)
|
||||
public void collectiveRepetitionsExceedTimeout() throws Exception {
|
||||
incrementInvocationCount();
|
||||
Thread.sleep(11);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
/**
|
||||
* Subclass #1 of {@link BaseAppCtxRuleTests}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class Subclass1AppCtxRuleTests extends BaseAppCtxRuleTests {
|
||||
|
||||
// All tests and config are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
/**
|
||||
* Subclass #2 of {@link BaseAppCtxRuleTests}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class Subclass2AppCtxRuleTests extends BaseAppCtxRuleTests {
|
||||
|
||||
// All tests and config are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.TimedSpringRunnerTests;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link TimedSpringRunnerTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class TimedSpringRuleTests extends TimedSpringRunnerTests {
|
||||
|
||||
// All tests are in superclass.
|
||||
|
||||
@Override
|
||||
protected Class<?> getTestCase() {
|
||||
return TimedSpringRuleTestCase.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Runner getRunner(Class<?> testClass) throws Exception {
|
||||
return new JUnit4(testClass);
|
||||
}
|
||||
|
||||
|
||||
@Ignore("TestCase classes are run manually by the enclosing test class")
|
||||
@TestExecutionListeners({})
|
||||
public static final class TimedSpringRuleTestCase extends TimedSpringRunnerTestCase {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
|
||||
/**
|
||||
* Overridden to always throw an exception, since Spring's Rule-based
|
||||
* JUnit integration does not fail a test for duplicate configuration
|
||||
* of timeouts.
|
||||
*/
|
||||
@Override
|
||||
public void springAndJUnitTimeouts() {
|
||||
fail("intentional failure to make tests in superclass pass");
|
||||
}
|
||||
|
||||
// All other tests are in superclass.
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import org.springframework.test.annotation.Repeat;
|
||||
import org.springframework.test.context.junit4.TimedTransactionalSpringRunnerTests;
|
||||
|
||||
import static org.springframework.test.transaction.TransactionTestUtils.*;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link TimedTransactionalSpringRunnerTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class TimedTransactionalSpringRuleTests extends TimedTransactionalSpringRunnerTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
@Rule
|
||||
public Timeout timeout = Timeout.builder().withTimeout(10, TimeUnit.SECONDS).build();
|
||||
|
||||
|
||||
/**
|
||||
* Overridden since Spring's Rule-based JUnit support cannot properly
|
||||
* integrate with timed execution that is controlled by a third-party runner.
|
||||
*/
|
||||
@Test(timeout = 10000)
|
||||
@Repeat(5)
|
||||
@Override
|
||||
public void transactionalWithJUnitTimeout() {
|
||||
assertInTransaction(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code timeout} explicitly not declared due to presence of Timeout rule.
|
||||
*/
|
||||
@Test
|
||||
public void transactionalWithJUnitRuleBasedTimeout() {
|
||||
assertInTransaction(true);
|
||||
}
|
||||
|
||||
// All other tests are in superclass.
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.rules;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.TransactionalSqlScriptsTests;
|
||||
|
||||
/**
|
||||
* This class is an extension of {@link TransactionalSqlScriptsTests}
|
||||
* that has been modified to use {@link SpringClassRule} and
|
||||
* {@link SpringMethodRule}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
// Note: @FixMethodOrder is NOT @Inherited.
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
// Overriding @Sql declaration to reference scripts using relative path.
|
||||
@Sql({ "../../jdbc/schema.sql", "../../jdbc/data.sql" })
|
||||
public class TransactionalSqlScriptsSpringRuleTests extends TransactionalSqlScriptsTests {
|
||||
|
||||
@ClassRule
|
||||
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
|
||||
|
||||
@Rule
|
||||
public final SpringMethodRule springMethodRule = new SpringMethodRule(this);
|
||||
|
||||
@Rule
|
||||
public Timeout timeout = Timeout.builder().withTimeout(10, TimeUnit.SECONDS).build();
|
||||
|
||||
|
||||
/**
|
||||
* Redeclared to ensure that {@code @FixMethodOrder} is properly applied.
|
||||
*/
|
||||
@Test
|
||||
@Override
|
||||
// test##_ prefix is required for @FixMethodOrder.
|
||||
public void test01_classLevelScripts() {
|
||||
assertNumUsers(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriding {@code @Sql} declaration to reference scripts using relative path.
|
||||
*/
|
||||
@Test
|
||||
@Sql({ "../../jdbc/drop-schema.sql", "../../jdbc/schema.sql", "../../jdbc/data.sql", "../../jdbc/data-add-dogbert.sql" })
|
||||
@Override
|
||||
// test##_ prefix is required for @FixMethodOrder.
|
||||
public void test02_methodLevelScripts() {
|
||||
assertNumUsers(2);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -25,16 +25,25 @@ import javax.sql.DataSource;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TestTransaction;
|
||||
import org.springframework.test.jdbc.JdbcTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -49,13 +58,28 @@ import static org.springframework.test.transaction.TransactionTestUtils.*;
|
|||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class ProgrammaticTxMgmtTests extends AbstractTransactionalJUnit4SpringContextTests {
|
||||
@Transactional
|
||||
public class ProgrammaticTxMgmtTests {
|
||||
|
||||
private String sqlScriptEncoding;
|
||||
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
protected ApplicationContext applicationContext;
|
||||
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
|
||||
@BeforeTransaction
|
||||
public void beforeTransaction() {
|
||||
deleteFromTables("user");
|
||||
|
@ -242,6 +266,15 @@ public class ProgrammaticTxMgmtTests extends AbstractTransactionalJUnit4SpringCo
|
|||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected int deleteFromTables(String... names) {
|
||||
return JdbcTestUtils.deleteFromTables(this.jdbcTemplate, names);
|
||||
}
|
||||
|
||||
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
|
||||
Resource resource = this.applicationContext.getResource(sqlResourcePath);
|
||||
new ResourceDatabasePopulator(continueOnError, false, this.sqlScriptEncoding, resource).execute(jdbcTemplate.getDataSource());
|
||||
}
|
||||
|
||||
private void assertUsers(String... users) {
|
||||
List<String> expected = Arrays.asList(users);
|
||||
Collections.sort(expected);
|
||||
|
@ -250,7 +283,6 @@ public class ProgrammaticTxMgmtTests extends AbstractTransactionalJUnit4SpringCo
|
|||
assertEquals("Users in database;", expected, actual);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
|
@ -264,7 +296,7 @@ public class ProgrammaticTxMgmtTests extends AbstractTransactionalJUnit4SpringCo
|
|||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()//
|
||||
.setName("programmatic-tx-mgmt-test-db")//
|
||||
.generateUniqueName(true)//
|
||||
.addScript("classpath:/org/springframework/test/context/jdbc/schema.sql") //
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -10,13 +10,17 @@ log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n
|
|||
log4j.rootCategory=ERROR, console, file
|
||||
|
||||
log4j.logger.org.springframework.beans=WARN
|
||||
|
||||
log4j.logger.org.springframework.test.context.TestContext=WARN
|
||||
log4j.logger.org.springframework.test.context.TestContextManager=WARN
|
||||
log4j.logger.org.springframework.test.context.ContextLoaderUtils=WARN
|
||||
log4j.logger.org.springframework.test.context.transaction.TransactionalTestExecutionListener=WARN
|
||||
log4j.logger.org.springframework.test.context.web=WARN
|
||||
log4j.logger.org.springframework.test.context=WARN
|
||||
log4j.logger.org.springframework.test.context.cache=WARN
|
||||
|
||||
log4j.logger.org.springframework.test.context.junit4.rules=WARN
|
||||
|
||||
#log4j.logger.org.springframework.test.context.support=INFO
|
||||
#log4j.logger.org.springframework.test.context.support.DelegatingSmartContextLoader=INFO
|
||||
#log4j.logger.org.springframework.test.context.support.AbstractGenericContextLoader=INFO
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="employee1" class="org.springframework.tests.sample.beans.Employee">
|
||||
<property name="name" value="John Smith" />
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
|
||||
p:driverClassName="org.hsqldb.jdbcDriver" p:url="jdbc:hsqldb:mem:transactional_tests" p:username="sa" p:password=""/>
|
||||
|
||||
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
|
||||
p:driverClassName="org.hsqldb.jdbcDriver" p:url="jdbc:hsqldb:mem:transactional_tests" p:username="sa" p:password=""/>
|
||||
<jdbc:embedded-database id="dataSource" generate-name="true" type="HSQL" />
|
||||
<jdbc:embedded-database id="dataSource2" generate-name="true" type="HSQL" />
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
|
||||
p:dataSource-ref="dataSource"/>
|
||||
p:dataSource-ref="dataSource" />
|
||||
|
||||
<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
|
||||
p:dataSource-ref="dataSource2">
|
||||
|
|
Loading…
Reference in New Issue