Skip to content

Commit e5d2570

Browse files
committed
[SPR-5145] Adding custom JUnit 4.5 Statements.
1 parent 8583026 commit e5d2570

File tree

7 files changed

+407
-60
lines changed

7 files changed

+407
-60
lines changed

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

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
2121
import org.junit.runner.RunWith;
22-
2322
import org.springframework.context.ApplicationContext;
2423
import org.springframework.context.ApplicationContextAware;
2524
import org.springframework.test.context.ContextConfiguration;
@@ -31,18 +30,17 @@
3130

3231
/**
3332
* <p>
34-
* Abstract base test class which integrates the
35-
* <em>Spring TestContext Framework</em> with explicit
36-
* {@link ApplicationContext} testing support in a <strong>JUnit 4.4</strong>
37-
* environment.
33+
* Abstract base test class which integrates the <em>Spring TestContext
34+
* Framework</em> with explicit {@link ApplicationContext} testing support in a
35+
* <strong>JUnit 4.5</strong> environment.
3836
* </p>
3937
* <p>
4038
* Concrete subclasses should typically declare a class-level
41-
* {@link ContextConfiguration @ContextConfiguration} annotation to configure
42-
* the {@link ApplicationContext application context}
39+
* {@link ContextConfiguration &#064;ContextConfiguration} annotation to
40+
* configure the {@link ApplicationContext application context}
4341
* {@link ContextConfiguration#locations() resource locations}.
4442
* <em>If your test does not need to load an application context, you may choose
45-
* to omit the {@link ContextConfiguration @ContextConfiguration} declaration
43+
* to omit the {@link ContextConfiguration &#064;ContextConfiguration} declaration
4644
* and to configure the appropriate
4745
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListeners}
4846
* manually.</em>
@@ -51,11 +49,11 @@
5149
* Note: this class serves only as a convenience for extension. If you do not
5250
* wish for your test classes to be tied to a Spring-specific class hierarchy,
5351
* you may configure your own custom test classes by using
54-
* {@link SpringJUnit4ClassRunner},
55-
* {@link ContextConfiguration @ContextConfiguration},
56-
* {@link TestExecutionListeners @TestExecutionListeners}, etc.
52+
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
53+
* &#064;ContextConfiguration}, {@link TestExecutionListeners
54+
* &#064;TestExecutionListeners}, etc.
5755
* </p>
58-
*
56+
*
5957
* @author Sam Brannen
6058
* @since 2.5
6159
* @see ContextConfiguration
@@ -66,7 +64,7 @@
6664
* @see org.springframework.test.context.testng.AbstractTestNGSpringContextTests
6765
*/
6866
@RunWith(SpringJUnit4ClassRunner.class)
69-
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
67+
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
7068
public abstract class AbstractJUnit4SpringContextTests implements ApplicationContextAware {
7169

7270
/**

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

+23-18
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@
5454
* Note: this class serves only as a convenience for extension. If you do not
5555
* wish for your test classes to be tied to a Spring-specific class hierarchy,
5656
* you may configure your own custom test classes by using
57-
* {@link SpringJUnit4ClassRunner},
58-
* {@link ContextConfiguration @ContextConfiguration},
59-
* {@link TestExecutionListeners @TestExecutionListeners},
60-
* {@link Transactional @Transactional}, etc.
57+
* {@link SpringJUnit4ClassRunner}, {@link ContextConfiguration
58+
* &#064;ContextConfiguration}, {@link TestExecutionListeners
59+
* &#064;TestExecutionListeners}, {@link Transactional &#064;Transactional},
60+
* etc.
6161
* </p>
62-
*
62+
*
6363
* @author Sam Brannen
6464
* @author Juergen Hoeller
6565
* @since 2.5
@@ -77,12 +77,13 @@
7777
* @see org.springframework.test.context.junit38.AbstractTransactionalJUnit38SpringContextTests
7878
* @see org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests
7979
*/
80-
@TestExecutionListeners({TransactionalTestExecutionListener.class})
80+
@TestExecutionListeners( { TransactionalTestExecutionListener.class })
8181
@Transactional
8282
public abstract class AbstractTransactionalJUnit4SpringContextTests extends AbstractJUnit4SpringContextTests {
8383

8484
/**
85-
* The SimpleJdbcTemplate that this base class manages, available to subclasses.
85+
* The SimpleJdbcTemplate that this base class manages, available to
86+
* subclasses.
8687
*/
8788
protected SimpleJdbcTemplate simpleJdbcTemplate;
8889

@@ -98,16 +99,18 @@ public void setDataSource(DataSource dataSource) {
9899
}
99100

100101
/**
101-
* Specify the encoding for SQL scripts, if different from the platform encoding.
102+
* Specify the encoding for SQL scripts, if different from the platform
103+
* encoding.
104+
*
102105
* @see #executeSqlScript
103106
*/
104107
public void setSqlScriptEncoding(String sqlScriptEncoding) {
105108
this.sqlScriptEncoding = sqlScriptEncoding;
106109
}
107110

108-
109111
/**
110112
* Count the rows in the given table.
113+
*
111114
* @param tableName table name to count rows in
112115
* @return the number of rows in the table
113116
*/
@@ -116,8 +119,9 @@ protected int countRowsInTable(String tableName) {
116119
}
117120

118121
/**
119-
* Convenience method for deleting all rows from the specified tables.
120-
* Use with caution outside of a transaction!
122+
* Convenience method for deleting all rows from the specified tables. Use
123+
* with caution outside of a transaction!
124+
*
121125
* @param names the names of the tables from which to delete
122126
* @return the total number of rows deleted from all specified tables
123127
*/
@@ -127,21 +131,22 @@ protected int deleteFromTables(String... names) {
127131

128132
/**
129133
* Execute the given SQL script. Use with caution outside of a transaction!
130-
* <p>The script will normally be loaded by classpath. There should be one statement
131-
* per line. Any semicolons will be removed. <b>Do not use this method to execute
132-
* DDL if you expect rollback.</b>
134+
* <p>
135+
* The script will normally be loaded by classpath. There should be one
136+
* statement per line. Any semicolons will be removed. <b>Do not use this
137+
* method to execute DDL if you expect rollback.</b>
138+
*
133139
* @param sqlResourcePath the Spring resource path for the SQL script
134140
* @param continueOnError whether or not to continue without throwing an
135141
* exception in the event of an error
136142
* @throws DataAccessException if there is an error executing a statement
137143
* and continueOnError was <code>false</code>
138144
*/
139-
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError)
140-
throws DataAccessException {
145+
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
141146

142147
Resource resource = this.applicationContext.getResource(sqlResourcePath);
143-
SimpleJdbcTestUtils.executeSqlScript(
144-
this.simpleJdbcTemplate, new EncodedResource(resource, this.sqlScriptEncoding), continueOnError);
148+
SimpleJdbcTestUtils.executeSqlScript(this.simpleJdbcTemplate, new EncodedResource(resource,
149+
this.sqlScriptEncoding), continueOnError);
145150
}
146151

147152
}

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

+39-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,39 +26,43 @@
2626
import org.junit.runner.Description;
2727
import org.junit.runner.notification.Failure;
2828
import org.junit.runner.notification.RunNotifier;
29-
3029
import org.springframework.test.annotation.ProfileValueUtils;
3130
import org.springframework.test.context.TestContextManager;
3231

3332
/**
3433
* <p>
3534
* SpringJUnit4ClassRunner is a custom extension of {@link JUnit4ClassRunner}
36-
* which provides functionality of the <em>Spring TestContext Framework</em>
37-
* to standard JUnit 4.4+ tests by means of the {@link TestContextManager} and
35+
* which provides functionality of the <em>Spring TestContext Framework</em> to
36+
* standard JUnit 4.5+ tests by means of the {@link TestContextManager} and
3837
* associated support classes and annotations.
3938
* </p>
4039
* <p>
4140
* The following list constitutes all annotations currently supported directly
42-
* by SpringJUnit4ClassRunner.
43-
* <em>(Note that additional annotations may be supported by various
44-
* {@link org.springframework.test.context.TestExecutionListener TestExecutionListeners})</em>
41+
* by SpringJUnit4ClassRunner. <em>(Note that additional annotations
42+
* may be supported by various
43+
* {@link org.springframework.test.context.TestExecutionListener
44+
* TestExecutionListeners})</em>
4545
* </p>
4646
* <ul>
47-
* <li>{@link org.junit.Test#expected() @Test(expected=...)}</li>
48-
* <li>{@link org.springframework.test.annotation.ExpectedException @ExpectedException}</li>
49-
* <li>{@link org.junit.Test#timeout() @Test(timeout=...)}</li>
50-
* <li>{@link org.springframework.test.annotation.Timed @Timed}</li>
51-
* <li>{@link org.springframework.test.annotation.Repeat @Repeat}</li>
52-
* <li>{@link org.junit.Ignore @Ignore}</li>
53-
* <li>{@link org.springframework.test.annotation.ProfileValueSourceConfiguration @ProfileValueSourceConfiguration}</li>
54-
* <li>{@link org.springframework.test.annotation.IfProfileValue @IfProfileValue}</li>
47+
* <li>{@link org.junit.Test#expected() &#064;Test(expected=...)}</li>
48+
* <li>{@link org.springframework.test.annotation.ExpectedException
49+
* &#064;ExpectedException}</li>
50+
* <li>{@link org.junit.Test#timeout() &#064;Test(timeout=...)}</li>
51+
* <li>{@link org.springframework.test.annotation.Timed &#064;Timed}</li>
52+
* <li>{@link org.springframework.test.annotation.Repeat &#064;Repeat}</li>
53+
* <li>{@link org.junit.Ignore &#064;Ignore}</li>
54+
* <li>
55+
* {@link org.springframework.test.annotation.ProfileValueSourceConfiguration
56+
* &#064;ProfileValueSourceConfiguration}</li>
57+
* <li>{@link org.springframework.test.annotation.IfProfileValue
58+
* &#064;IfProfileValue}</li>
5559
* </ul>
56-
*
57-
* <p><b>NOTE:</b> As of Spring 3.0 M1, SpringJUnit4ClassRunner requires
58-
* JUnit 4.5, while internally still being based on JUnit 4.4 SPI.
59-
* This will be rewritten based on JUnit 4.5's BlockJUnit4ClassRunner
60-
* in a later Spring 3.0 release.
61-
*
60+
* <p>
61+
* <b>NOTE:</b> As of Spring 3.0 M1, SpringJUnit4ClassRunner requires JUnit 4.5,
62+
* while internally still being based on JUnit 4.4 SPI. This will be rewritten
63+
* based on JUnit 4.5's BlockJUnit4ClassRunner in a later Spring 3.0 release.
64+
* </p>
65+
*
6266
* @author Sam Brannen
6367
* @author Juergen Hoeller
6468
* @since 2.5
@@ -75,6 +79,7 @@ public class SpringJUnit4ClassRunner extends JUnit4ClassRunner {
7579
* Constructs a new <code>SpringJUnit4ClassRunner</code> and initializes a
7680
* {@link TestContextManager} to provide Spring testing functionality to
7781
* standard JUnit tests.
82+
*
7883
* @param clazz the Class object corresponding to the test class to be run
7984
* @see #createTestContextManager(Class)
8085
*/
@@ -86,15 +91,16 @@ public SpringJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
8691
this.testContextManager = createTestContextManager(clazz);
8792
}
8893

89-
90-
@Override
9194
/**
92-
* Check whether the test is enabled in the first place. This prevents classes with
93-
* a non-matching <code>@IfProfileValue</code> annotation from running altogether,
94-
* even skipping the execution of <code>prepareTestInstance</code> listener methods.
95+
* Check whether the test is enabled in the first place. This prevents
96+
* classes with a non-matching <code>&#064;IfProfileValue</code> annotation
97+
* from running altogether, even skipping the execution of
98+
* <code>prepareTestInstance</code> listener methods.
99+
*
95100
* @see org.springframework.test.annotation.IfProfileValue
96101
* @see org.springframework.test.context.TestExecutionListener
97102
*/
103+
@Override
98104
public void run(RunNotifier notifier) {
99105
if (!ProfileValueUtils.isTestEnabledInThisEnvironment(getTestClass().getJavaClass())) {
100106
notifier.fireTestIgnored(getDescription());
@@ -108,6 +114,7 @@ public void run(RunNotifier notifier) {
108114
* instance and then to a {@link TestContextManager} to
109115
* {@link TestContextManager#prepareTestInstance(Object) prepare} the test
110116
* instance for Spring testing functionality.
117+
*
111118
* @see JUnit4ClassRunner#createTest()
112119
* @see TestContextManager#prepareTestInstance(Object)
113120
*/
@@ -119,8 +126,11 @@ protected Object createTest() throws Exception {
119126
}
120127

121128
/**
122-
* Creates a new {@link TestContextManager}. Can be overridden by subclasses.
123-
* @param clazz the Class object corresponding to the test class to be managed
129+
* Creates a new {@link TestContextManager}. Can be overridden by
130+
* subclasses.
131+
*
132+
* @param clazz the Class object corresponding to the test class to be
133+
* managed
124134
*/
125135
protected TestContextManager createTestContextManager(Class<?> clazz) {
126136
return new TestContextManager(clazz);
@@ -136,6 +146,7 @@ protected final TestContextManager getTestContextManager() {
136146
/**
137147
* Invokes the supplied {@link Method test method} and notifies the supplied
138148
* {@link RunNotifier} of the appropriate events.
149+
*
139150
* @see #createTest()
140151
* @see JUnit4ClassRunner#invokeTestMethod(Method,RunNotifier)
141152
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.junit4.statements;
18+
19+
import java.lang.reflect.Method;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
import org.junit.internal.runners.model.MultipleFailureException;
24+
import org.junit.runners.model.Statement;
25+
import org.springframework.test.context.TestContextManager;
26+
27+
/**
28+
* <code>RunSpringTestContextAfters</code> is a custom JUnit 4.5+
29+
* {@link Statement} which allows the <em>Spring TestContext Framework</em> to
30+
* be plugged into the JUnit execution chain by calling
31+
* {@link TestContextManager#afterTestMethod(Object, Method) afterTestMethod()}
32+
* on the supplied {@link TestContextManager}.
33+
*
34+
* @see #evaluate()
35+
* @see RunSpringTestContextBefores
36+
* @author Sam Brannen
37+
* @since 3.0
38+
*/
39+
public class RunSpringTestContextAfters extends Statement {
40+
41+
private final Statement next;
42+
43+
private final Object testInstance;
44+
45+
private final Method testMethod;
46+
47+
private final TestContextManager testContextManager;
48+
49+
50+
/**
51+
* Constructs a new <code>RunSpringTestContextAfters</code> statement.
52+
*
53+
* @param next the next <code>Statement</code> in the execution chain
54+
* @param testInstance the current test instance (never <code>null</code>)
55+
* @param testMethod the test method which has just been executed on the
56+
* test instance
57+
* @param testContextManager the TestContextManager upon which to call
58+
* <code>afterTestMethod()</code>
59+
*/
60+
public RunSpringTestContextAfters(Statement next, Object testInstance, Method testMethod,
61+
TestContextManager testContextManager) {
62+
this.next = next;
63+
this.testInstance = testInstance;
64+
this.testMethod = testMethod;
65+
this.testContextManager = testContextManager;
66+
}
67+
68+
/**
69+
* Invokes the next {@link Statement} in the execution chain (typically an
70+
* instance of {@link org.junit.internal.runners.statements.RunAfters
71+
* RunAfters}), catching any exceptions thrown, and then calls
72+
* {@link TestContextManager#afterTestMethod(Object, Method)} with the first
73+
* caught exception (if any). If the call to <code>afterTestMethod()</code>
74+
* throws an exception, it will also be tracked. Multiple exceptions will be
75+
* combined into a {@link MultipleFailureException}.
76+
*/
77+
@Override
78+
public void evaluate() throws Throwable {
79+
Throwable testException = null;
80+
List<Throwable> errors = new ArrayList<Throwable>();
81+
try {
82+
this.next.evaluate();
83+
}
84+
catch (Throwable e) {
85+
testException = e;
86+
errors.add(e);
87+
}
88+
89+
try {
90+
this.testContextManager.afterTestMethod(this.testInstance, this.testMethod, testException);
91+
}
92+
catch (Exception e) {
93+
errors.add(e);
94+
}
95+
96+
if (errors.isEmpty()) {
97+
return;
98+
}
99+
if (errors.size() == 1) {
100+
throw errors.get(0);
101+
}
102+
throw new MultipleFailureException(errors);
103+
}
104+
}

0 commit comments

Comments
 (0)