|
|
|
@ -182,7 +182,7 @@ public class EventPublishingTestExecutionListenerIntegrationTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@RunWith(SpringRunner.class) |
|
|
|
@RunWith(SpringRunner.class) |
|
|
|
@ContextConfiguration(classes = EventCaptureConfiguration.class) |
|
|
|
@ContextConfiguration(classes = TestEventListenerConfiguration.class) |
|
|
|
@TestExecutionListeners(listeners = EventPublishingTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) |
|
|
|
@TestExecutionListeners(listeners = EventPublishingTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) |
|
|
|
public static class ExampleTestCase { |
|
|
|
public static class ExampleTestCase { |
|
|
|
|
|
|
|
|
|
|
|
@ -211,7 +211,7 @@ public class EventPublishingTestExecutionListenerIntegrationTests { |
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
@Configuration |
|
|
|
@EnableAsync(proxyTargetClass = true) |
|
|
|
@EnableAsync(proxyTargetClass = true) |
|
|
|
static class EventCaptureConfiguration extends AsyncConfigurerSupport { |
|
|
|
static class TestEventListenerConfiguration extends AsyncConfigurerSupport { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Executor getAsyncExecutor() { |
|
|
|
public Executor getAsyncExecutor() { |
|
|
|
@ -231,88 +231,97 @@ public class EventPublishingTestExecutionListenerIntegrationTests { |
|
|
|
return mock(TestExecutionListener.class); |
|
|
|
return mock(TestExecutionListener.class); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The {@code @Async} test event listener method must reside in a separate |
|
|
|
|
|
|
|
* component since {@code @Async} is not supported on methods in |
|
|
|
|
|
|
|
* {@code @Configuration} classes. |
|
|
|
|
|
|
|
*/ |
|
|
|
@Bean |
|
|
|
@Bean |
|
|
|
EventCaptureBean eventCaptureBean() { |
|
|
|
AsyncTestEventComponent asyncTestEventComponent() { |
|
|
|
return new EventCaptureBean(listener()); |
|
|
|
return new AsyncTestEventComponent(listener()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static class TrackingAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static volatile Throwable asyncException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void handleUncaughtException(Throwable exception, Method method, Object... params) { |
|
|
|
|
|
|
|
asyncException = exception; |
|
|
|
|
|
|
|
countDownLatch.countDown(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MUST be annotated with @Component due to a change in Spring 5.1 that
|
|
|
|
|
|
|
|
// does not consider beans in a package starting with "org.springframework"
|
|
|
|
|
|
|
|
// to be event listeners unless they are also components. See
|
|
|
|
|
|
|
|
// org.springframework.context.event.EventListenerMethodProcessor.isSpringContainerClass(Class<?>)
|
|
|
|
|
|
|
|
// for details.
|
|
|
|
|
|
|
|
@Component |
|
|
|
|
|
|
|
static class EventCaptureBean { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final TestExecutionListener listener; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EventCaptureBean(TestExecutionListener listener) { |
|
|
|
|
|
|
|
this.listener = listener; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestClass("#root.event.source.testClass.name matches '.+TestCase'") |
|
|
|
@BeforeTestClass("#root.event.source.testClass.name matches '.+TestCase'") |
|
|
|
public void beforeTestClass(BeforeTestClassEvent e) throws Exception { |
|
|
|
public void beforeTestClass(BeforeTestClassEvent e) throws Exception { |
|
|
|
this.listener.beforeTestClass(e.getSource()); |
|
|
|
listener().beforeTestClass(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@PrepareTestInstance("#a0.testContext.testClass.name matches '.+TestCase'") |
|
|
|
@PrepareTestInstance("#a0.testContext.testClass.name matches '.+TestCase'") |
|
|
|
public void prepareTestInstance(PrepareTestInstanceEvent e) throws Exception { |
|
|
|
public void prepareTestInstance(PrepareTestInstanceEvent e) throws Exception { |
|
|
|
this.listener.prepareTestInstance(e.getSource()); |
|
|
|
listener().prepareTestInstance(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestMethod("#p0.testContext.testMethod.isAnnotationPresent(T(org.springframework.test.context.event.EventPublishingTestExecutionListenerIntegrationTests.Traceable))") |
|
|
|
@BeforeTestMethod("#p0.testContext.testMethod.isAnnotationPresent(T(org.springframework.test.context.event.EventPublishingTestExecutionListenerIntegrationTests.Traceable))") |
|
|
|
public void beforeTestMethod(BeforeTestMethodEvent e) throws Exception { |
|
|
|
public void beforeTestMethod(BeforeTestMethodEvent e) throws Exception { |
|
|
|
this.listener.beforeTestMethod(e.getSource()); |
|
|
|
listener().beforeTestMethod(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestMethod("event.testContext.testMethod.name == 'testWithFailingEventListener'") |
|
|
|
@BeforeTestMethod("event.testContext.testMethod.name == 'testWithFailingEventListener'") |
|
|
|
public void beforeTestMethodWithFailure(BeforeTestMethodEvent event) throws Exception { |
|
|
|
public void beforeTestMethodWithFailure(BeforeTestMethodEvent event) throws Exception { |
|
|
|
this.listener.beforeTestMethod(event.getSource()); |
|
|
|
listener().beforeTestMethod(event.getSource()); |
|
|
|
throw new RuntimeException("Boom!"); |
|
|
|
throw new RuntimeException("Boom!"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestMethod("event.testContext.testMethod.name == 'testWithFailingAsyncEventListener'") |
|
|
|
|
|
|
|
@Async |
|
|
|
|
|
|
|
public void beforeTestMethodWithAsyncFailure(BeforeTestMethodEvent event) throws Exception { |
|
|
|
|
|
|
|
this.listener.beforeTestMethod(event.getSource()); |
|
|
|
|
|
|
|
throw new RuntimeException(String.format("Asynchronous exception for test method [%s] in thread [%s]", |
|
|
|
|
|
|
|
event.getTestContext().getTestMethod().getName(), Thread.currentThread().getName())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestExecution |
|
|
|
@BeforeTestExecution |
|
|
|
public void beforeTestExecution(BeforeTestExecutionEvent e) throws Exception { |
|
|
|
public void beforeTestExecution(BeforeTestExecutionEvent e) throws Exception { |
|
|
|
this.listener.beforeTestExecution(e.getSource()); |
|
|
|
listener().beforeTestExecution(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@AfterTestExecution |
|
|
|
@AfterTestExecution |
|
|
|
public void afterTestExecution(AfterTestExecutionEvent e) throws Exception { |
|
|
|
public void afterTestExecution(AfterTestExecutionEvent e) throws Exception { |
|
|
|
this.listener.afterTestExecution(e.getSource()); |
|
|
|
listener().afterTestExecution(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@AfterTestMethod("event.testContext.testMethod.isAnnotationPresent(T(org.springframework.test.context.event.EventPublishingTestExecutionListenerIntegrationTests.Traceable))") |
|
|
|
@AfterTestMethod("event.testContext.testMethod.isAnnotationPresent(T(org.springframework.test.context.event.EventPublishingTestExecutionListenerIntegrationTests.Traceable))") |
|
|
|
public void afterTestMethod(AfterTestMethodEvent e) throws Exception { |
|
|
|
public void afterTestMethod(AfterTestMethodEvent e) throws Exception { |
|
|
|
this.listener.afterTestMethod(e.getSource()); |
|
|
|
listener().afterTestMethod(e.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@AfterTestClass("#afterTestClassEvent.testContext.testClass.name matches '.+TestCase'") |
|
|
|
@AfterTestClass("#afterTestClassEvent.testContext.testClass.name matches '.+TestCase'") |
|
|
|
public void afterTestClass(AfterTestClassEvent afterTestClassEvent) throws Exception { |
|
|
|
public void afterTestClass(AfterTestClassEvent afterTestClassEvent) throws Exception { |
|
|
|
this.listener.afterTestClass(afterTestClassEvent.getSource()); |
|
|
|
listener().afterTestClass(afterTestClassEvent.getSource()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* MUST be annotated with {@code @Component} due to a change in Spring 5.1 that |
|
|
|
|
|
|
|
* does not consider beans in a package starting with "org.springframework" to be |
|
|
|
|
|
|
|
* event listeners unless they are also components. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @see org.springframework.context.event.EventListenerMethodProcessor#isSpringContainerClass |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Component |
|
|
|
|
|
|
|
static class AsyncTestEventComponent { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final TestExecutionListener listener; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AsyncTestEventComponent(TestExecutionListener listener) { |
|
|
|
|
|
|
|
this.listener = listener; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeTestMethod("event.testContext.testMethod.name == 'testWithFailingAsyncEventListener'") |
|
|
|
|
|
|
|
@Async |
|
|
|
|
|
|
|
public void beforeTestMethodWithAsyncFailure(BeforeTestMethodEvent event) throws Exception { |
|
|
|
|
|
|
|
this.listener.beforeTestMethod(event.getSource()); |
|
|
|
|
|
|
|
throw new RuntimeException(String.format("Asynchronous exception for test method [%s] in thread [%s]", |
|
|
|
|
|
|
|
event.getTestContext().getTestMethod().getName(), Thread.currentThread().getName())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static class TrackingAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static volatile Throwable asyncException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void handleUncaughtException(Throwable exception, Method method, Object... params) { |
|
|
|
|
|
|
|
asyncException = exception; |
|
|
|
|
|
|
|
countDownLatch.countDown(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|