Browse Source

[SPR-5145] Adding custom JUnit 4.5 Statements.

conversation
Sam Brannen 16 years ago
parent
commit
e5d2570c8d
  1. 26
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/AbstractJUnit4SpringContextTests.java
  2. 41
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java
  3. 67
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunner.java
  4. 104
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/RunSpringTestContextAfters.java
  5. 77
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/RunSpringTestContextBefores.java
  6. 76
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/SpringFailOnTimeout.java
  7. 76
      org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/SpringRepeat.java

26
org.springframework.test/src/main/java/org/springframework/test/context/junit4/AbstractJUnit4SpringContextTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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,7 +19,6 @@ package org.springframework.test.context.junit4; @@ -19,7 +19,6 @@ 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;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
@ -31,18 +30,17 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe @@ -31,18 +30,17 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
/**
* <p>
* Abstract base test class which integrates the
* <em>Spring TestContext Framework</em> with explicit
* {@link ApplicationContext} testing support in a <strong>JUnit 4.4</strong>
* environment.
* Abstract base test class which integrates the <em>Spring TestContext
* Framework</em> with explicit {@link ApplicationContext} testing support in a
* <strong>JUnit 4.5</strong> environment.
* </p>
* <p>
* Concrete subclasses should typically declare a class-level
* {@link ContextConfiguration @ContextConfiguration} annotation to configure
* the {@link ApplicationContext application context}
* {@link ContextConfiguration &#064;ContextConfiguration} annotation to
* configure the {@link ApplicationContext application context}
* {@link ContextConfiguration#locations() resource locations}.
* <em>If your test does not need to load an application context, you may choose
* to omit the {@link ContextConfiguration @ContextConfiguration} declaration
* to omit the {@link ContextConfiguration &#064;ContextConfiguration} declaration
* and to configure the appropriate
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListeners}
* manually.</em>
@ -51,11 +49,11 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe @@ -51,11 +49,11 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
* 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.
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
* &#064;ContextConfiguration}, {@link TestExecutionListeners
* &#064;TestExecutionListeners}, etc.
* </p>
*
*
* @author Sam Brannen
* @since 2.5
* @see ContextConfiguration
@ -66,7 +64,7 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe @@ -66,7 +64,7 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
* @see org.springframework.test.context.testng.AbstractTestNGSpringContextTests
*/
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
public abstract class AbstractJUnit4SpringContextTests implements ApplicationContextAware {
/**

41
org.springframework.test/src/main/java/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.java

@ -54,12 +54,12 @@ import org.springframework.transaction.annotation.Transactional; @@ -54,12 +54,12 @@ import org.springframework.transaction.annotation.Transactional;
* 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.
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
* &#064;ContextConfiguration}, {@link TestExecutionListeners
* &#064;TestExecutionListeners}, {@link Transactional &#064;Transactional},
* etc.
* </p>
*
*
* @author Sam Brannen
* @author Juergen Hoeller
* @since 2.5
@ -77,12 +77,13 @@ import org.springframework.transaction.annotation.Transactional; @@ -77,12 +77,13 @@ import org.springframework.transaction.annotation.Transactional;
* @see org.springframework.test.context.junit38.AbstractTransactionalJUnit38SpringContextTests
* @see org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests
*/
@TestExecutionListeners({TransactionalTestExecutionListener.class})
@TestExecutionListeners( { TransactionalTestExecutionListener.class })
@Transactional
public abstract class AbstractTransactionalJUnit4SpringContextTests extends AbstractJUnit4SpringContextTests {
/**
* The SimpleJdbcTemplate that this base class manages, available to subclasses.
* The SimpleJdbcTemplate that this base class manages, available to
* subclasses.
*/
protected SimpleJdbcTemplate simpleJdbcTemplate;
@ -98,16 +99,18 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst @@ -98,16 +99,18 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
}
/**
* Specify the encoding for SQL scripts, if different from the platform encoding.
* Specify the encoding for SQL scripts, if different from the platform
* encoding.
*
* @see #executeSqlScript
*/
public void setSqlScriptEncoding(String sqlScriptEncoding) {
this.sqlScriptEncoding = sqlScriptEncoding;
}
/**
* Count the rows in the given table.
*
* @param tableName table name to count rows in
* @return the number of rows in the table
*/
@ -116,8 +119,9 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst @@ -116,8 +119,9 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
}
/**
* Convenience method for deleting all rows from the specified tables.
* Use with caution outside of a transaction!
* Convenience method for deleting all rows from the specified tables. Use
* with caution outside of a transaction!
*
* @param names the names of the tables from which to delete
* @return the total number of rows deleted from all specified tables
*/
@ -127,21 +131,22 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst @@ -127,21 +131,22 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
/**
* Execute the given SQL script. Use with caution outside of a transaction!
* <p>The script will normally be loaded by classpath. There should be one statement
* per line. Any semicolons will be removed. <b>Do not use this method to execute
* DDL if you expect rollback.</b>
* <p>
* The script will normally be loaded by classpath. There should be one
* statement per line. Any semicolons will be removed. <b>Do not use this
* method to execute DDL if you expect rollback.</b>
*
* @param sqlResourcePath the Spring resource path for the SQL script
* @param continueOnError whether or not to continue without throwing an
* exception in the event of an error
* @throws DataAccessException if there is an error executing a statement
* and continueOnError was <code>false</code>
*/
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError)
throws DataAccessException {
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
Resource resource = this.applicationContext.getResource(sqlResourcePath);
SimpleJdbcTestUtils.executeSqlScript(
this.simpleJdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding), continueOnError);
SimpleJdbcTestUtils.executeSqlScript(this.simpleJdbcTemplate, new EncodedResource(resource,
this.sqlScriptEncoding), continueOnError);
}
}

67
org.springframework.test/src/main/java/org/springframework/test/context/junit4/SpringJUnit4ClassRunner.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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.
@ -26,39 +26,43 @@ import org.junit.internal.runners.JUnit4ClassRunner; @@ -26,39 +26,43 @@ import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.springframework.test.annotation.ProfileValueUtils;
import org.springframework.test.context.TestContextManager;
/**
* <p>
* SpringJUnit4ClassRunner is a custom extension of {@link JUnit4ClassRunner}
* which provides functionality of the <em>Spring TestContext Framework</em>
* to standard JUnit 4.4+ tests by means of the {@link TestContextManager} and
* which provides functionality of the <em>Spring TestContext Framework</em> to
* standard JUnit 4.5+ tests by means of the {@link TestContextManager} and
* associated support classes and annotations.
* </p>
* <p>
* The following list constitutes all annotations currently supported directly
* by SpringJUnit4ClassRunner.
* <em>(Note that additional annotations may be supported by various
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListeners})</em>
* by SpringJUnit4ClassRunner. <em>(Note that additional annotations
* may be supported by various
* {@link org.springframework.test.context.TestExecutionListener
* TestExecutionListeners})</em>
* </p>
* <ul>
* <li>{@link org.junit.Test#expected() @Test(expected=...)}</li>
* <li>{@link org.springframework.test.annotation.ExpectedException @ExpectedException}</li>
* <li>{@link org.junit.Test#timeout() @Test(timeout=...)}</li>
* <li>{@link org.springframework.test.annotation.Timed @Timed}</li>
* <li>{@link org.springframework.test.annotation.Repeat @Repeat}</li>
* <li>{@link org.junit.Ignore @Ignore}</li>
* <li>{@link org.springframework.test.annotation.ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}</li>
* <li>{@link org.springframework.test.annotation.IfProfileValue @IfProfileValue}</li>
* <li>{@link org.junit.Test#expected() &#064;Test(expected=...)}</li>
* <li>{@link org.springframework.test.annotation.ExpectedException
* &#064;ExpectedException}</li>
* <li>{@link org.junit.Test#timeout() &#064;Test(timeout=...)}</li>
* <li>{@link org.springframework.test.annotation.Timed &#064;Timed}</li>
* <li>{@link org.springframework.test.annotation.Repeat &#064;Repeat}</li>
* <li>{@link org.junit.Ignore &#064;Ignore}</li>
* <li>
* {@link org.springframework.test.annotation.ProfileValueSourceConfiguration
* &#064;ProfileValueSourceConfiguration}</li>
* <li>{@link org.springframework.test.annotation.IfProfileValue
* &#064;IfProfileValue}</li>
* </ul>
*
* <p><b>NOTE:</b> As of Spring 3.0 M1, SpringJUnit4ClassRunner requires
* JUnit 4.5, while internally still being based on JUnit 4.4 SPI.
* This will be rewritten based on JUnit 4.5's BlockJUnit4ClassRunner
* in a later Spring 3.0 release.
*
* <p>
* <b>NOTE:</b> As of Spring 3.0 M1, SpringJUnit4ClassRunner requires JUnit 4.5,
* while internally still being based on JUnit 4.4 SPI. This will be rewritten
* based on JUnit 4.5's BlockJUnit4ClassRunner in a later Spring 3.0 release.
* </p>
*
* @author Sam Brannen
* @author Juergen Hoeller
* @since 2.5
@ -75,6 +79,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner { @@ -75,6 +79,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
* Constructs a new <code>SpringJUnit4ClassRunner</code> and initializes a
* {@link TestContextManager} to provide Spring testing functionality to
* standard JUnit tests.
*
* @param clazz the Class object corresponding to the test class to be run
* @see #createTestContextManager(Class)
*/
@ -86,15 +91,16 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner { @@ -86,15 +91,16 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
this.testContextManager = createTestContextManager(clazz);
}
@Override
/**
* Check whether the test is enabled in the first place. This prevents classes with
* a non-matching <code>@IfProfileValue</code> annotation from running altogether,
* even skipping the execution of <code>prepareTestInstance</code> listener methods.
* Check whether the test is enabled in the first place. This prevents
* classes with a non-matching <code>&#064;IfProfileValue</code> annotation
* from running altogether, even skipping the execution of
* <code>prepareTestInstance</code> listener methods.
*
* @see org.springframework.test.annotation.IfProfileValue
* @see org.springframework.test.context.TestExecutionListener
*/
@Override
public void run(RunNotifier notifier) {
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(getTestClass().getJavaClass())) {
notifier.fireTestIgnored(getDescription());
@ -108,6 +114,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner { @@ -108,6 +114,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
* instance and then to a {@link TestContextManager} to
* {@link TestContextManager#prepareTestInstance(Object) prepare} the test
* instance for Spring testing functionality.
*
* @see JUnit4ClassRunner#createTest()
* @see TestContextManager#prepareTestInstance(Object)
*/
@ -119,8 +126,11 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner { @@ -119,8 +126,11 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
}
/**
* Creates a new {@link TestContextManager}. Can be overridden by subclasses.
* @param clazz the Class object corresponding to the test class to be managed
* Creates a new {@link TestContextManager}. Can be overridden by
* subclasses.
*
* @param clazz the Class object corresponding to the test class to be
* managed
*/
protected TestContextManager createTestContextManager(Class<?> clazz) {
return new TestContextManager(clazz);
@ -136,6 +146,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner { @@ -136,6 +146,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
/**
* Invokes the supplied {@link Method test method} and notifies the supplied
* {@link RunNotifier} of the appropriate events.
*
* @see #createTest()
* @see JUnit4ClassRunner#invokeTestMethod(Method,RunNotifier)
*/

104
org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/RunSpringTestContextAfters.java

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
/*
* Copyright 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.statements;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.internal.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
import org.springframework.test.context.TestContextManager;
/**
* <code>RunSpringTestContextAfters</code> is a custom JUnit 4.5+
* {@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) afterTestMethod()}
* on the supplied {@link TestContextManager}.
*
* @see #evaluate()
* @see RunSpringTestContextBefores
* @author Sam Brannen
* @since 3.0
*/
public class RunSpringTestContextAfters extends Statement {
private final Statement next;
private final Object testInstance;
private final Method testMethod;
private final TestContextManager testContextManager;
/**
* Constructs a new <code>RunSpringTestContextAfters</code> statement.
*
* @param next the next <code>Statement</code> in the execution chain
* @param testInstance the current test instance (never <code>null</code>)
* @param testMethod the test method which has just been executed on the
* test instance
* @param testContextManager the TestContextManager upon which to call
* <code>afterTestMethod()</code>
*/
public RunSpringTestContextAfters(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}
/**
* Invokes the next {@link Statement} in the execution chain (typically an
* instance of {@link org.junit.internal.runners.statements.RunAfters
* RunAfters}), catching any exceptions thrown, and then calls
* {@link TestContextManager#afterTestMethod(Object, Method)} with the first
* caught exception (if any). If the call to <code>afterTestMethod()</code>
* throws an exception, it will also be tracked. Multiple exceptions will be
* combined into a {@link MultipleFailureException}.
*/
@Override
public void evaluate() throws Throwable {
Throwable testException = null;
List<Throwable> errors = new ArrayList<Throwable>();
try {
this.next.evaluate();
}
catch (Throwable e) {
testException = e;
errors.add(e);
}
try {
this.testContextManager.afterTestMethod(this.testInstance, this.testMethod, testException);
}
catch (Exception e) {
errors.add(e);
}
if (errors.isEmpty()) {
return;
}
if (errors.size() == 1) {
throw errors.get(0);
}
throw new MultipleFailureException(errors);
}
}

77
org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/RunSpringTestContextBefores.java

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
/*
* Copyright 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.statements;
import java.lang.reflect.Method;
import org.junit.runners.model.Statement;
import org.springframework.test.context.TestContextManager;
/**
* <code>RunSpringTestContextBefores</code> is a custom JUnit 4.5+
* {@link Statement} which allows the <em>Spring TestContext Framework</em> to
* be plugged into the JUnit execution chain by calling
* {@link TestContextManager#beforeTestMethod(Object, Method)
* beforeTestMethod()} on the supplied {@link TestContextManager}.
*
* @see #evaluate()
* @see RunSpringTestContextAfters
* @author Sam Brannen
* @since 3.0
*/
public class RunSpringTestContextBefores extends Statement {
private final Statement next;
private final Object testInstance;
private final Method testMethod;
private final TestContextManager testContextManager;
/**
* Constructs a new <code>RunSpringTestContextBefores</code> statement.
*
* @param next the next <code>Statement</code> in the execution chain
* @param testInstance the current test instance (never <code>null</code>)
* @param testMethod the test method which is about to be executed on the
* test instance
* @param testContextManager the TestContextManager upon which to call
* <code>beforeTestMethod()</code>
*/
public RunSpringTestContextBefores(Statement next, Object testInstance, Method testMethod,
TestContextManager testContextManager) {
this.next = next;
this.testInstance = testInstance;
this.testMethod = testMethod;
this.testContextManager = testContextManager;
}
/**
* Calls {@link TestContextManager#beforeTestMethod(Object, Method)} and
* then invokes the next {@link Statement} in the execution chain (typically
* an instance of {@link org.junit.internal.runners.statements.RunBefores
* RunBefores} ).
*/
@Override
public void evaluate() throws Throwable {
this.testContextManager.beforeTestMethod(this.testInstance, this.testMethod);
this.next.evaluate();
}
}

76
org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/SpringFailOnTimeout.java

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
/*
* Copyright 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.statements;
import java.util.concurrent.TimeoutException;
import org.junit.runners.model.Statement;
import org.springframework.test.annotation.Timed;
/**
* <code>SpringFailOnTimeout</code> is a custom JUnit 4.5+ {@link Statement}
* which adds support for Spring's {@link Timed @Timed} annotation by throwing
* an exception if the next statement in the execution chain takes more than the
* specified number of milliseconds.
*
* @see #evaluate()
* @author Sam Brannen
* @since 3.0
*/
public class SpringFailOnTimeout extends Statement {
private final Statement next;
private final long timeout;
/**
* Constructs a new <code>SpringFailOnTimeout</code> statement.
*
* @param next the next <code>Statement</code> in the execution chain
* @param timeout the configured <code>timeout</code> for the current test
* @see Timed#millis()
*/
public SpringFailOnTimeout(Statement next, long timeout) {
this.next = next;
this.timeout = timeout;
}
/**
* Invokes 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 throws an exception if the next
* <code>statement</code> takes more than the specified <code>timeout</code>
* .
*/
@Override
public void evaluate() throws Throwable {
long startTime = System.currentTimeMillis();
try {
this.next.evaluate();
}
finally {
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > this.timeout) {
throw new TimeoutException(String.format("Test took %s ms; limit was %s ms.", elapsed, this.timeout));
}
}
}
}

76
org.springframework.test/src/main/java/org/springframework/test/context/junit4/statements/SpringRepeat.java

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
/*
* Copyright 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.statements;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.runners.model.Statement;
import org.springframework.test.annotation.Repeat;
import org.springframework.util.ClassUtils;
/**
* <code>SpringRepeat</code> is a custom JUnit 4.5+ {@link Statement} which adds
* support for Spring's {@link Repeat &#064;Repeat} annotation by repeating the
* test for the specified number of times.
*
* @see #evaluate()
* @author Sam Brannen
* @since 3.0
*/
public class SpringRepeat extends Statement {
protected static final Log logger = LogFactory.getLog(SpringRepeat.class);
private final Statement next;
private final Method testMethod;
private final int repeat;
/**
* Constructs a new <code>SpringRepeat</code> statement.
*
* @param next the next <code>Statement</code> in the execution chain
* @param testMethod the current test method
* @param repeat the configured repeat count for the current test method
* @see Repeat#value()
*/
public SpringRepeat(Statement next, Method testMethod, int repeat) {
this.next = next;
this.testMethod = testMethod;
this.repeat = Math.max(1, repeat);
}
/**
* Invokes the next {@link Statement statement} in the execution chain for
* the specified repeat count.
*/
@Override
public void evaluate() throws Throwable {
for (int i = 0; i < this.repeat; i++) {
if (this.repeat > 1 && logger.isInfoEnabled()) {
logger.info(String.format("Repetition %d of test %s#%s()", (i + 1),
ClassUtils.getShortName(this.testMethod.getDeclaringClass()), this.testMethod.getName()));
}
this.next.evaluate();
}
}
}
Loading…
Cancel
Save