27
27
import org .apache .commons .logging .Log ;
28
28
import org .apache .commons .logging .LogFactory ;
29
29
30
+ import org .springframework .beans .BeanInstantiationException ;
30
31
import org .springframework .beans .BeanUtils ;
31
32
import org .springframework .core .annotation .AnnotationUtils ;
32
33
import org .springframework .util .Assert ;
49
50
* <ul>
50
51
* <li>{@link #beforeTestClass() before test class execution}: prior to any
51
52
* <em>before class methods</em> of a particular testing framework (e.g., JUnit
52
- * 4's {@link org.junit.BeforeClass @ BeforeClass})</li>
53
+ * 4's {@link org.junit.BeforeClass @ BeforeClass})</li>
53
54
* <li>{@link #prepareTestInstance(Object) test instance preparation}:
54
55
* immediately following instantiation of the test instance</li>
55
56
* <li>{@link #beforeTestMethod(Object, Method) before test method execution}:
56
57
* prior to any <em>before methods</em> of a particular testing framework (e.g.,
57
- * JUnit 4's {@link org.junit.Before @ Before})</li>
58
+ * JUnit 4's {@link org.junit.Before @ Before})</li>
58
59
* <li>{@link #afterTestMethod(Object, Method, Throwable) after test method
59
60
* execution}: after any <em>after methods</em> of a particular testing
60
- * framework (e.g., JUnit 4's {@link org.junit.After @ After})</li>
61
+ * framework (e.g., JUnit 4's {@link org.junit.After @ After})</li>
61
62
* <li>{@link #afterTestClass() after test class execution}: after any
62
63
* <em>after class methods</em> of a particular testing framework (e.g., JUnit
63
- * 4's {@link org.junit.AfterClass @ AfterClass})</li>
64
+ * 4's {@link org.junit.AfterClass @ AfterClass})</li>
64
65
* </ul>
65
66
*
66
67
* @author Sam Brannen
74
75
public class TestContextManager {
75
76
76
77
private static final String [] DEFAULT_TEST_EXECUTION_LISTENER_CLASS_NAMES = new String [] {
77
- "org.springframework.test.context.web.ServletTestExecutionListener" ,
78
- "org.springframework.test.context.support.DependencyInjectionTestExecutionListener" ,
79
- "org.springframework.test.context.support.DirtiesContextTestExecutionListener" ,
80
- "org.springframework.test.context.transaction.TransactionalTestExecutionListener" };
78
+ "org.springframework.test.context.web.ServletTestExecutionListener" ,
79
+ "org.springframework.test.context.support.DependencyInjectionTestExecutionListener" ,
80
+ "org.springframework.test.context.support.DirtiesContextTestExecutionListener" ,
81
+ "org.springframework.test.context.transaction.TransactionalTestExecutionListener" };
81
82
82
83
private static final Log logger = LogFactory .getLog (TestContextManager .class );
83
84
@@ -164,10 +165,10 @@ private List<TestExecutionListener> getReversedTestExecutionListeners() {
164
165
165
166
/**
166
167
* Retrieve an array of newly instantiated {@link TestExecutionListener TestExecutionListeners}
167
- * for the specified {@link Class class}. If {@link TestExecutionListeners @ TestExecutionListeners}
168
+ * for the specified {@link Class class}. If {@link TestExecutionListeners @ TestExecutionListeners}
168
169
* is not <em>present</em> on the supplied class, the default listeners will be returned.
169
170
* <p>Note that the {@link TestExecutionListeners#inheritListeners() inheritListeners} flag of
170
- * {@link TestExecutionListeners @ TestExecutionListeners} will be taken into consideration.
171
+ * {@link TestExecutionListeners @ TestExecutionListeners} will be taken into consideration.
171
172
* Specifically, if the {@code inheritListeners} flag is set to {@code true}, listeners
172
173
* defined in the annotated class will be appended to the listeners defined in superclasses.
173
174
* @param clazz the test class for which the listeners should be retrieved
@@ -198,12 +199,10 @@ private TestExecutionListener[] retrieveTestExecutionListeners(Class<?> clazz) {
198
199
Class <? extends TestExecutionListener >[] valueListenerClasses = testExecutionListeners .value ();
199
200
Class <? extends TestExecutionListener >[] listenerClasses = testExecutionListeners .listeners ();
200
201
if (!ObjectUtils .isEmpty (valueListenerClasses ) && !ObjectUtils .isEmpty (listenerClasses )) {
201
- String msg = String .format ("Test class [%s] has been configured with @TestExecutionListeners' " +
202
- "'value' [%s] and 'listeners' [%s] attributes. Use one or the other, but not both." ,
202
+ throw new IllegalStateException ( String .format ("Class [%s] configured with @TestExecutionListeners' " +
203
+ "'value' [%s] and 'listeners' [%s] attributes. Use one or the other, but not both." ,
203
204
declaringClass , ObjectUtils .nullSafeToString (valueListenerClasses ),
204
- ObjectUtils .nullSafeToString (listenerClasses ));
205
- logger .error (msg );
206
- throw new IllegalStateException (msg );
205
+ ObjectUtils .nullSafeToString (listenerClasses )));
207
206
}
208
207
else if (!ObjectUtils .isEmpty (valueListenerClasses )) {
209
208
listenerClasses = valueListenerClasses ;
@@ -213,20 +212,30 @@ else if (!ObjectUtils.isEmpty(valueListenerClasses)) {
213
212
classesList .addAll (0 , Arrays .<Class <? extends TestExecutionListener >> asList (listenerClasses ));
214
213
}
215
214
declaringClass = (testExecutionListeners .inheritListeners () ? AnnotationUtils .findAnnotationDeclaringClass (
216
- annotationType , declaringClass .getSuperclass ()) : null );
215
+ annotationType , declaringClass .getSuperclass ()) : null );
217
216
}
218
217
}
219
218
220
219
List <TestExecutionListener > listeners = new ArrayList <TestExecutionListener >(classesList .size ());
221
220
for (Class <? extends TestExecutionListener > listenerClass : classesList ) {
221
+ NoClassDefFoundError ncdfe = null ;
222
222
try {
223
223
listeners .add (BeanUtils .instantiateClass (listenerClass ));
224
224
}
225
225
catch (NoClassDefFoundError err ) {
226
+ ncdfe = err ;
227
+ }
228
+ catch (BeanInstantiationException ex ) {
229
+ if (ex .getCause () instanceof NoClassDefFoundError ) {
230
+ ncdfe = (NoClassDefFoundError ) ex .getCause ();
231
+ }
232
+ }
233
+ if (ncdfe != null ) {
226
234
if (logger .isInfoEnabled ()) {
227
- logger .info (String .format ("Could not instantiate TestExecutionListener class [%s]. " +
235
+ logger .info (String .format ("Could not instantiate TestExecutionListener [%s]. " +
228
236
"Specify custom listener classes or make the default listener classes " +
229
- "(and their dependencies) available." , listenerClass .getName ()));
237
+ "(and their required dependencies) available. Offending class: [%s]" ,
238
+ listenerClass .getName (), ncdfe .getMessage ()));
230
239
}
231
240
}
232
241
}
@@ -258,7 +267,7 @@ protected Set<Class<? extends TestExecutionListener>> getDefaultTestExecutionLis
258
267
* Hook for pre-processing a test class <em>before</em> execution of any
259
268
* tests within the class. Should be called prior to any framework-specific
260
269
* <em>before class methods</em> (e.g., methods annotated with JUnit's
261
- * {@link org.junit.BeforeClass @ BeforeClass}).
270
+ * {@link org.junit.BeforeClass @ BeforeClass}).
262
271
* <p>An attempt will be made to give each registered
263
272
* {@link TestExecutionListener} a chance to pre-process the test class
264
273
* execution. If a listener throws an exception, however, the remaining
@@ -324,7 +333,7 @@ public void prepareTestInstance(Object testInstance) throws Exception {
324
333
* {@link Method test method}, for example for setting up test fixtures,
325
334
* starting a transaction, etc. Should be called prior to any
326
335
* framework-specific <em>before methods</em> (e.g., methods annotated with
327
- * JUnit's {@link org.junit.Before @ Before}).
336
+ * JUnit's {@link org.junit.Before @ Before}).
328
337
* <p>The managed {@link TestContext} will be updated with the supplied
329
338
* {@code testInstance} and {@code testMethod}.
330
339
* <p>An attempt will be made to give each registered
@@ -362,7 +371,7 @@ public void beforeTestMethod(Object testInstance, Method testMethod) throws Exce
362
371
* {@link Method test method}, for example for tearing down test fixtures,
363
372
* ending a transaction, etc. Should be called after any framework-specific
364
373
* <em>after methods</em> (e.g., methods annotated with JUnit's
365
- * {@link org.junit.After @ After}).
374
+ * {@link org.junit.After @ After}).
366
375
* <p>The managed {@link TestContext} will be updated with the supplied
367
376
* {@code testInstance}, {@code testMethod}, and
368
377
* {@code exception}.
@@ -414,7 +423,7 @@ public void afterTestMethod(Object testInstance, Method testMethod, Throwable ex
414
423
* Hook for post-processing a test class <em>after</em> execution of all
415
424
* tests within the class. Should be called after any framework-specific
416
425
* <em>after class methods</em> (e.g., methods annotated with JUnit's
417
- * {@link org.junit.AfterClass @ AfterClass}).
426
+ * {@link org.junit.AfterClass @ AfterClass}).
418
427
* <p>Each registered {@link TestExecutionListener} will be given a chance to
419
428
* post-process the test class. If a listener throws an exception, the
420
429
* remaining registered listeners will still be called, but the first
0 commit comments