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:
Sam Brannen
2015-05-08 20:46:18 +02:00
parent 49fff7513d
commit d1b1c4f888
40 changed files with 1970 additions and 168 deletions

View File

@@ -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. */

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 &#064;BeforeTransaction} and
* {@link AfterTransaction &#064;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() {

View File

@@ -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 })

View File

@@ -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());
}
}

View File

@@ -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. */

View File

@@ -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 &#064;Repeat}</li>
* <li>Spring's {@link Timed &#064;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 {

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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.
}

View File

@@ -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.
}

View File

@@ -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.
}

View File

@@ -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()");
}
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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.
}

View File

@@ -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.
}

View File

@@ -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.
}
}

View File

@@ -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.
}

View File

@@ -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);
}
}

View File

@@ -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();
}