diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java
new file mode 100644
index 00000000000..1ce10ff9ca3
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/ExpectedExceptionSpringRunnerTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2009 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;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.JUnit4;
+import org.springframework.test.annotation.ExpectedException;
+import org.springframework.test.context.TestExecutionListeners;
+
+/**
+ * Verifies proper handling of the following in conjunction with the
+ * {@link SpringJUnit4ClassRunner}:
+ *
+ * JUnit's {@link Test#expected() @Test(expected=...)}
+ * Spring's {@link ExpectedException @ExpectedException}
+ *
+ *
+ * @author Sam Brannen
+ * @since 3.0
+ */
+@RunWith(JUnit4.class)
+public class ExpectedExceptionSpringRunnerTests {
+
+ @Test
+ public void timedTests() throws Exception {
+ 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 + "].", 1,
+ listener.getTestFailureCount());
+ assertEquals("Verifying number of tests started for test class [" + testClass + "].", 3,
+ listener.getTestStartedCount());
+ assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 3,
+ listener.getTestFinishedCount());
+ }
+
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+ @TestExecutionListeners( {})
+ public static final class ExpectedExceptionSpringRunnerTestCase {
+
+ // Should Pass.
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void verifyJUnitExpectedException() {
+ new ArrayList().get(1);
+ }
+
+ // Should Pass.
+ @Test
+ @ExpectedException(IndexOutOfBoundsException.class)
+ public void verifySpringExpectedException() {
+ new ArrayList().get(1);
+ }
+
+ // Should Fail due to duplicate configuration.
+ @Test(expected = IllegalStateException.class)
+ @ExpectedException(IllegalStateException.class)
+ public void verifyJUnitAndSpringExpectedException() {
+ new ArrayList().get(1);
+ }
+
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java
index a1fcc57abe2..ec5ffd493fd 100644
--- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/FailingBeforeAndAfterMethodsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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.
@@ -17,18 +17,16 @@
package org.springframework.test.context.junit4;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
@@ -39,15 +37,15 @@ import org.springframework.test.context.transaction.BeforeTransaction;
/**
*
- * JUnit 4 based unit test for verifying that 'before ' and 'after '
- * 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 before' and '
+ * after ' 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 SPR-3960 .
*
- *
+ *
* @author Sam Brannen
* @since 2.5
*/
@@ -63,39 +61,23 @@ public class FailingBeforeAndAfterMethodsTests {
@Parameters
public static Collection testData() {
- return Arrays.asList(new Object[][] {
-
- { AlwaysFailingBeforeTestMethodTestCase.class },
-
- { AlwaysFailingAfterTestMethodTestCase.class },
-
- { FailingBeforeTransactionalTestCase.class },
-
- { FailingAfterTransactionalTestCase.class }
-
+ return Arrays.asList(new Object[][] {//
+ //
+ { AlwaysFailingBeforeTestMethodTestCase.class },//
+ { AlwaysFailingAfterTestMethodTestCase.class },//
+ { FailingBeforeTransactionalTestCase.class },//
+ { FailingAfterTransactionalTestCase.class } //
});
}
@Test
public void runTestAndAssertCounters() throws Exception {
- final FailureTrackingRunListener failureTrackingRunListener = new FailureTrackingRunListener();
+ final TrackingRunListener listener = new TrackingRunListener();
final RunNotifier notifier = new RunNotifier();
- notifier.addListener(failureTrackingRunListener);
+ notifier.addListener(listener);
new SpringJUnit4ClassRunner(this.clazz).run(notifier);
- assertEquals("Verifying number of failures for test class [" + this.clazz + "].", 1,
- failureTrackingRunListener.failureCount);
- }
-
-
- static class FailureTrackingRunListener extends RunListener {
-
- int failureCount = 0;
-
-
- public void testFailure(Failure failure) throws Exception {
- this.failureCount++;
- }
+ assertEquals("Verifying number of failures for test class [" + this.clazz + "].", 1, listener.getTestFailureCount());
}
@@ -103,20 +85,18 @@ public class FailingBeforeAndAfterMethodsTests {
@Override
public void beforeTestMethod(TestContext testContext) {
- org.junit.Assert.fail("always failing beforeTestMethod()");
+ fail("always failing beforeTestMethod()");
}
}
-
static class AlwaysFailingAfterTestMethodTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void afterTestMethod(TestContext testContext) {
- org.junit.Assert.fail("always failing afterTestMethod()");
+ fail("always failing afterTestMethod()");
}
}
-
@TestExecutionListeners(value = { AlwaysFailingBeforeTestMethodTestExecutionListener.class }, inheritListeners = false)
public static class AlwaysFailingBeforeTestMethodTestCase extends AbstractJUnit4SpringContextTests {
@@ -125,7 +105,6 @@ public class FailingBeforeAndAfterMethodsTests {
}
}
-
@TestExecutionListeners(value = { AlwaysFailingAfterTestMethodTestExecutionListener.class }, inheritListeners = false)
public static class AlwaysFailingAfterTestMethodTestCase extends AbstractJUnit4SpringContextTests {
@@ -134,7 +113,6 @@ public class FailingBeforeAndAfterMethodsTests {
}
}
-
@ContextConfiguration(locations = { "FailingBeforeAndAfterMethodsTests-context.xml" })
public static class FailingBeforeTransactionalTestCase extends AbstractTransactionalJUnit4SpringContextTests {
@@ -144,11 +122,10 @@ public class FailingBeforeAndAfterMethodsTests {
@BeforeTransaction
public void beforeTransaction() {
- org.junit.Assert.fail("always failing beforeTransaction()");
+ fail("always failing beforeTransaction()");
}
}
-
@ContextConfiguration(locations = { "FailingBeforeAndAfterMethodsTests-context.xml" })
public static class FailingAfterTransactionalTestCase extends AbstractTransactionalJUnit4SpringContextTests {
@@ -158,7 +135,7 @@ public class FailingBeforeAndAfterMethodsTests {
@AfterTransaction
public void afterTransaction() {
- org.junit.Assert.fail("always failing afterTransaction()");
+ fail("always failing afterTransaction()");
}
}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java
new file mode 100644
index 00000000000..40c1d59c10c
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/RepeatedSpringRunnerTests.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2002-2009 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;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.springframework.test.annotation.Repeat;
+import org.springframework.test.annotation.Timed;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+
+/**
+ * Verifies proper handling of the following in conjunction with the
+ * {@link SpringJUnit4ClassRunner}:
+ *
+ * Spring's {@link Repeat @Repeat}
+ * Spring's {@link Timed @Timed}
+ *
+ *
+ * @author Sam Brannen
+ * @since 3.0
+ */
+@RunWith(Parameterized.class)
+public class RepeatedSpringRunnerTests {
+
+ private static final AtomicInteger invocationCount = new AtomicInteger();
+
+ private final Class extends AbstractRepeatedTestCase> testClass;
+
+ private final int expectedFailureCount;
+
+ private final int expectedTestStartedCount;
+
+ private final int expectedTestFinishedCount;
+
+ private final int expectedInvocationCount;
+
+
+ public RepeatedSpringRunnerTests(Class extends AbstractRepeatedTestCase> testClass, int expectedFailureCount,
+ int expectedTestStartedCount, int expectedTestFinishedCount, int expectedInvocationCount) {
+ this.testClass = testClass;
+ this.expectedFailureCount = expectedFailureCount;
+ this.expectedTestStartedCount = expectedTestStartedCount;
+ this.expectedTestFinishedCount = expectedTestFinishedCount;
+ this.expectedInvocationCount = expectedInvocationCount;
+ }
+
+ @Parameters
+ public static Collection repetitionData() {
+ return Arrays.asList(new Object[][] {//
+ //
+ { NonAnnotatedRepeatedTestCase.class, 0, 1, 1, 1 },//
+ { DefaultRepeatValueRepeatedTestCase.class, 0, 1, 1, 1 },//
+ { NegativeRepeatValueRepeatedTestCase.class, 0, 1, 1, 1 },//
+ { RepeatedFiveTimesRepeatedTestCase.class, 0, 1, 1, 5 } //
+ });
+ }
+
+ @Test
+ public void assertRepetitions() throws Exception {
+ TrackingRunListener listener = new TrackingRunListener();
+ RunNotifier notifier = new RunNotifier();
+ 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());
+ }
+
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+ @TestExecutionListeners( {})
+ @ContextConfiguration(locations = {})
+ public abstract static class AbstractRepeatedTestCase {
+
+ protected void incrementInvocationCount() throws IOException {
+ invocationCount.incrementAndGet();
+ }
+ }
+
+ public static final class NonAnnotatedRepeatedTestCase extends AbstractRepeatedTestCase {
+
+ @Test
+ @Timed(millis = 10000)
+ public void testNonAnnotated() throws Exception {
+ incrementInvocationCount();
+ }
+ }
+
+ public static final class DefaultRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase {
+
+ @Test
+ @Repeat
+ @Timed(millis = 10000)
+ public void testDefaultRepeatValue() throws Exception {
+ incrementInvocationCount();
+ }
+ }
+
+ public static final class NegativeRepeatValueRepeatedTestCase extends AbstractRepeatedTestCase {
+
+ @Test
+ @Repeat(-5)
+ @Timed(millis = 10000)
+ public void testNegativeRepeatValue() throws Exception {
+ incrementInvocationCount();
+ }
+ }
+
+ public static final class RepeatedFiveTimesRepeatedTestCase extends AbstractRepeatedTestCase {
+
+ @Test
+ @Repeat(5)
+ @Timed(millis = 10000)
+ public void testRepeatedFiveTimes() throws Exception {
+ incrementInvocationCount();
+ }
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java
index 8484f1a720c..7d2289a5a64 100644
--- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2009 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,13 +19,12 @@ package org.springframework.test.context.junit4;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
-
import org.springframework.test.context.SpringRunnerContextCacheTests;
/**
*
- * JUnit 4 based test suite for tests involving {@link SpringJUnit4ClassRunner},
- * {@link SpringMethodRoadie}, and Spring's annotation-based test support.
+ * JUnit 4 based test suite for tests involving {@link SpringJUnit4ClassRunner}
+ * and the Spring TestContext Framework .
*
*
* This test suite serves a dual purpose of verifying that tests run with
@@ -37,57 +36,38 @@ import org.springframework.test.context.SpringRunnerContextCacheTests;
* from an automated build process, test runner, etc. that is configured to run
* tests based on a "*Tests.class" pattern match.
*
- *
+ *
* @author Sam Brannen
* @since 2.5
*/
@RunWith(Suite.class)
// Note: the following 'multi-line' layout is for enhanced code readability.
-@SuiteClasses( {
-
-StandardJUnit4FeaturesTests.class,
-
-StandardJUnit4FeaturesSpringRunnerTests.class,
-
-EnabledAndIgnoredSpringRunnerTests.class,
-
-HardCodedProfileValueSourceSpringRunnerTests.class,
-
-SpringJUnit4ClassRunnerAppCtxTests.class,
-
-ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.class,
-
-AbsolutePathSpringJUnit4ClassRunnerAppCtxTests.class,
-
-RelativePathSpringJUnit4ClassRunnerAppCtxTests.class,
-
-MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.class,
-
-InheritedConfigSpringJUnit4ClassRunnerAppCtxTests.class,
-
-PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.class,
-
-SpringRunnerContextCacheTests.class,
-
-ParameterizedDependencyInjectionTests.class,
-
-ClassLevelTransactionalSpringRunnerTests.class,
-
-MethodLevelTransactionalSpringRunnerTests.class,
-
-DefaultRollbackTrueTransactionalSpringRunnerTests.class,
-
-DefaultRollbackFalseTransactionalSpringRunnerTests.class,
-
-RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.class,
-
-RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class,
-
-BeforeAndAfterTransactionAnnotationTests.class,
-
-TimedTransactionalSpringRunnerTests.class
-
+@SuiteClasses( {//
+StandardJUnit4FeaturesTests.class,//
+ StandardJUnit4FeaturesSpringRunnerTests.class,//
+ ExpectedExceptionSpringRunnerTests.class,//
+ TimedSpringRunnerTests.class,//
+ RepeatedSpringRunnerTests.class,//
+ EnabledAndIgnoredSpringRunnerTests.class,//
+ HardCodedProfileValueSourceSpringRunnerTests.class,//
+ SpringJUnit4ClassRunnerAppCtxTests.class,//
+ ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.class,//
+ AbsolutePathSpringJUnit4ClassRunnerAppCtxTests.class,//
+ RelativePathSpringJUnit4ClassRunnerAppCtxTests.class,//
+ MultipleResourcesSpringJUnit4ClassRunnerAppCtxTests.class,//
+ InheritedConfigSpringJUnit4ClassRunnerAppCtxTests.class,//
+ PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests.class,//
+ SpringRunnerContextCacheTests.class,//
+ ParameterizedDependencyInjectionTests.class,//
+ ClassLevelTransactionalSpringRunnerTests.class,//
+ MethodLevelTransactionalSpringRunnerTests.class,//
+ DefaultRollbackTrueTransactionalSpringRunnerTests.class,//
+ DefaultRollbackFalseTransactionalSpringRunnerTests.class,//
+ RollbackOverrideDefaultRollbackTrueTransactionalSpringRunnerTests.class,//
+ RollbackOverrideDefaultRollbackFalseTransactionalSpringRunnerTests.class,//
+ BeforeAndAfterTransactionAnnotationTests.class,//
+ TimedTransactionalSpringRunnerTests.class //
})
public class SpringJUnit4SuiteTests {
- /* this test case is comprised completely of tests loaded as a suite. */
+ /* this test case consists entirely of tests loaded as a suite. */
}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java
new file mode 100644
index 00000000000..a3033eba07e
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TimedSpringRunnerTests.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2002-2009 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;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.JUnit4;
+import org.springframework.test.annotation.Timed;
+import org.springframework.test.context.TestExecutionListeners;
+
+/**
+ * Verifies proper handling of the following in conjunction with the
+ * {@link SpringJUnit4ClassRunner}:
+ *
+ * JUnit's {@link Test#timeout() @Test(timeout=...)}
+ * Spring's {@link Timed @Timed}
+ *
+ *
+ * @author Sam Brannen
+ * @since 3.0
+ */
+@RunWith(JUnit4.class)
+public class TimedSpringRunnerTests {
+
+ @Test
+ public void timedTests() throws Exception {
+ Class testClass = TimedSpringRunnerTestCase.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 + "].", 3,
+ listener.getTestFailureCount());
+ assertEquals("Verifying number of tests started for test class [" + testClass + "].", 5,
+ listener.getTestStartedCount());
+ assertEquals("Verifying number of tests finished for test class [" + testClass + "].", 5,
+ listener.getTestFinishedCount());
+ }
+
+
+ @RunWith(SpringJUnit4ClassRunner.class)
+ @TestExecutionListeners( {})
+ public static final class TimedSpringRunnerTestCase {
+
+ // Should Pass.
+ @Test(timeout = 2000)
+ public void testJUnitTimeoutWithNoOp() {
+ /* no-op */
+ }
+
+ // Should Pass.
+ @Test
+ @Timed(millis = 2000)
+ public void testSpringTimeoutWithNoOp() {
+ /* no-op */
+ }
+
+ // Should Fail due to timeout.
+ @Test(timeout = 200)
+ public void testJUnitTimeoutWithOneSecondWait() throws Exception {
+ Thread.sleep(1000);
+ }
+
+ // Should Fail due to timeout.
+ @Test
+ @Timed(millis = 200)
+ public void testSpringTimeoutWithOneSecondWait() throws Exception {
+ Thread.sleep(1000);
+ }
+
+ // Should Fail due to duplicate configuration.
+ @Test(timeout = 200)
+ @Timed(millis = 200)
+ public void testSpringAndJUnitTimeout() {
+ /* no-op */
+ }
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java
new file mode 100644
index 00000000000..6a8edd857ca
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/TrackingRunListener.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2009 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;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * Simple {@link RunListener} which tracks how many times certain JUnit callback
+ * methods were called: only intended for the integration test suite.
+ *
+ * @author Sam Brannen
+ * @since 3.0
+ */
+public class TrackingRunListener extends RunListener {
+
+ private final AtomicInteger testFailureCount = new AtomicInteger();
+
+ private final AtomicInteger testStartedCount = new AtomicInteger();
+
+ private final AtomicInteger testFinishedCount = new AtomicInteger();
+
+
+ public int getTestFailureCount() {
+ return this.testFailureCount.get();
+ }
+
+ public int getTestStartedCount() {
+ return this.testStartedCount.get();
+ }
+
+ public int getTestFinishedCount() {
+ return this.testFinishedCount.get();
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ this.testFailureCount.incrementAndGet();
+ }
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ this.testStartedCount.incrementAndGet();
+ }
+
+ @Override
+ public void testFinished(Description description) throws Exception {
+ this.testFinishedCount.incrementAndGet();
+ }
+
+}