diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java index 327cacb17e5c..8cae398efea1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java @@ -56,6 +56,8 @@ * TransactionalTestExecutionListener} *
These events may be consumed for various reasons, such as resetting {@em mock} beans or tracing test + * execution. Since these events may consumed as part of regular Spring beans, they can be shared among + * different test classes. + * + *
This {@link org.springframework.test.context.TestExecutionListener} is not active by default. Test classes + * should be annotated using {@link org.springframework.test.context.TestExecutionListeners}, if they want to use it. + * Alternatively, it may be added to {@code spring.factories}, if needed. + * + * @author Frank Scheffler + * @since 5.2 + * @see org.springframework.test.context.event.annotation.BeforeTestClass + * @see org.springframework.test.context.event.annotation.PrepareTestInstance + * @see org.springframework.test.context.event.annotation.BeforeTestMethod + * @see org.springframework.test.context.event.annotation.BeforeTestExecution + * @see org.springframework.test.context.event.annotation.AfterTestExecution + * @see org.springframework.test.context.event.annotation.AfterTestMethod + * @see org.springframework.test.context.event.annotation.AfterTestClass + */ +public class EventPublishingTestExecutionListener extends AbstractTestExecutionListener { + + @Override + public void beforeTestClass(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new BeforeTestClassEvent(testContext)); + } + + @Override + public void prepareTestInstance(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new PrepareTestInstanceEvent(testContext)); + } + + @Override + public void beforeTestMethod(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new BeforeTestMethodEvent(testContext)); + } + + @Override + public void beforeTestExecution(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new BeforeTestExecutionEvent(testContext)); + } + + @Override + public void afterTestExecution(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new AfterTestExecutionEvent(testContext)); + } + + @Override + public void afterTestMethod(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new AfterTestMethodEvent(testContext)); + } + + @Override + public void afterTestClass(TestContext testContext) { + testContext.getApplicationContext().publishEvent( + new AfterTestClassEvent(testContext)); + } +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/PrepareTestInstanceEvent.java b/spring-test/src/main/java/org/springframework/test/context/event/PrepareTestInstanceEvent.java new file mode 100644 index 000000000000..5a26fb80008b --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/PrepareTestInstanceEvent.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2019 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.event; + +import org.springframework.test.context.TestContext; + +/** + * {@link TestContextEvent} published by {@link EventPublishingTestExecutionListener} when + * {@link org.springframework.test.context.TestExecutionListener#prepareTestInstance(TestContext)} is called. + * + * @author Frank Scheffler + * @since 5.2 + * @see org.springframework.test.context.event.annotation.PrepareTestInstance + */ +@SuppressWarnings("serial") +public class PrepareTestInstanceEvent extends TestContextEvent { + + public PrepareTestInstanceEvent(TestContext source) { + super(source); + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/TestContextEvent.java b/spring-test/src/main/java/org/springframework/test/context/event/TestContextEvent.java new file mode 100644 index 000000000000..20a3787b8942 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/TestContextEvent.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2019 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.event; + +import org.springframework.context.ApplicationEvent; +import org.springframework.test.context.TestContext; + +/** + * Base class for events published by {@link EventPublishingTestExecutionListener}. + * + * @author Frank Scheffler + * @since 5.2 + */ +@SuppressWarnings("serial") +public abstract class TestContextEvent extends ApplicationEvent { + + public TestContextEvent(TestContext source) { + super(source); + } + + /* + * (non-Javadoc) + * + * @see java.util.EventObject#getSource() + */ + @Override + public TestContext getSource() { + return (TestContext) super.getSource(); + } +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestClass.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestClass.java new file mode 100644 index 000000000000..b4e7ddb6fcfc --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestClass.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.AfterTestClassEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link AfterTestClassEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#afterTestClass(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see AfterTestClassEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(AfterTestClassEvent.class) +public @interface AfterTestClass { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestExecution.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestExecution.java new file mode 100644 index 000000000000..642699d70cd1 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestExecution.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.AfterTestExecutionEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link AfterTestExecutionEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#afterTestExecution(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see AfterTestExecutionEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(AfterTestExecutionEvent.class) +public @interface AfterTestExecution { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestMethod.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestMethod.java new file mode 100644 index 000000000000..89a6fc422cbb --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/AfterTestMethod.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.AfterTestMethodEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link AfterTestMethodEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#afterTestMethod(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see AfterTestMethodEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(AfterTestMethodEvent.class) +public @interface AfterTestMethod { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestClass.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestClass.java new file mode 100644 index 000000000000..29badc02c3ea --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestClass.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.BeforeTestClassEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link BeforeTestClassEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#beforeTestClass(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see BeforeTestClassEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(BeforeTestClassEvent.class) +public @interface BeforeTestClass { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestExecution.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestExecution.java new file mode 100644 index 000000000000..b9fa796b57c3 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestExecution.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.BeforeTestExecutionEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link BeforeTestExecutionEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#beforeTestExecution(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see BeforeTestExecutionEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(BeforeTestExecutionEvent.class) +public @interface BeforeTestExecution { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestMethod.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestMethod.java new file mode 100644 index 000000000000..d7a7483ffc28 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/BeforeTestMethod.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.BeforeTestMethodEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link BeforeTestMethodEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#beforeTestMethod(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled, + * for this annotation to have an effect, e.g. by annotation your test class with + * {@link org.springframework.test.context.TestExecutionListeners} accordingly. + * + * @author Frank Scheffler + * @since 5.2 + * @see BeforeTestMethodEvent + */ +@Documented +@Retention(RUNTIME) +@Target({METHOD, ANNOTATION_TYPE}) +@EventListener(BeforeTestMethodEvent.class) +public @interface BeforeTestMethod { +} diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/PrepareTestInstance.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/PrepareTestInstance.java new file mode 100644 index 000000000000..e410c58552ef --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/PrepareTestInstance.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-2019 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.event.annotation; + +import org.springframework.context.event.EventListener; +import org.springframework.test.context.event.PrepareTestInstanceEvent; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@link EventListener} annotation used to consume {@link PrepareTestInstanceEvent}s published + * by {@link org.springframework.test.context.event.EventPublishingTestExecutionListener}. + * + *
This annotation may be used on {@link EventListener}-compliant methods within the Spring test + * {@link org.springframework.context.ApplicationContext}, typically within + * {@link org.springframework.context.annotation.Configuration}s. A method annotated hereby will be + * called as part of the {@link org.springframework.test.context.TestExecutionListener#prepareTestInstance(org.springframework.test.context.TestContext)} + * life-cycle method. + * + *
Make sure {@link org.springframework.test.context.event.EventPublishingTestExecutionListener} is enabled,
+ * for this annotation to have an effect, e.g. by annotation your test class with
+ * {@link org.springframework.test.context.TestExecutionListeners} accordingly.
+ *
+ * @author Frank Scheffler
+ * @since 5.2
+ * @see PrepareTestInstanceEvent
+ */
+@Documented
+@Retention(RUNTIME)
+@Target({METHOD, ANNOTATION_TYPE})
+@EventListener(PrepareTestInstanceEvent.class)
+public @interface PrepareTestInstance {
+}
diff --git a/spring-test/src/main/java/org/springframework/test/context/event/annotation/package-info.java b/spring-test/src/main/java/org/springframework/test/context/event/annotation/package-info.java
new file mode 100644
index 000000000000..efc10e414a7f
--- /dev/null
+++ b/spring-test/src/main/java/org/springframework/test/context/event/annotation/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Test event annotations for the Spring TestContext Framework.
+ */
+package org.springframework.test.context.event.annotation;
\ No newline at end of file
diff --git a/spring-test/src/main/java/org/springframework/test/context/event/package-info.java b/spring-test/src/main/java/org/springframework/test/context/event/package-info.java
new file mode 100644
index 000000000000..3d8677b979a9
--- /dev/null
+++ b/spring-test/src/main/java/org/springframework/test/context/event/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Test event support classes for the Spring TestContext Framework.
+ */
+package org.springframework.test.context.event;
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerIntegrationTests.java
new file mode 100644
index 000000000000..910e107c25a4
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerIntegrationTests.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2019 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.event;
+
+import java.lang.reflect.Method;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.TestContextManager;
+import org.springframework.test.context.TestExecutionListener;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.event.annotation.*;
+import org.springframework.util.ReflectionUtils;
+
+import static org.mockito.BDDMockito.*;
+
+/**
+ * Integration test for {@link EventPublishingTestExecutionListener} and
+ * accompanying {@link TestContextEvent} annotations.
+ *
+ * @author Frank Scheffler
+ * @since 5.2
+ */
+public class EventPublishingTestExecutionListenerIntegrationTests {
+
+ private TestContextManager testContextManager;
+ private TestContext testContext;
+ private TestExecutionListener trigger;
+ private Object testInstance;
+ private Method testMethod;
+
+ @Configuration
+ static class EventCaptureConfiguration {
+ @Bean
+ public TestExecutionListener trigger() {
+ return mock(TestExecutionListener.class);
+ }
+
+ @BeforeTestClass
+ public void beforeTestClass(BeforeTestClassEvent e) throws Exception {
+ trigger().beforeTestClass(e.getSource());
+ }
+
+ @PrepareTestInstance
+ public void prepareTestInstance(PrepareTestInstanceEvent e) throws Exception {
+ trigger().prepareTestInstance(e.getSource());
+ }
+
+
+ @BeforeTestMethod
+ public void beforeTestMethod(BeforeTestMethodEvent e) throws Exception {
+ trigger().beforeTestMethod(e.getSource());
+ }
+
+ @BeforeTestExecution
+ public void beforeTestExecutiob(BeforeTestExecutionEvent e) throws Exception {
+ trigger().beforeTestExecution(e.getSource());
+ }
+
+ @AfterTestExecution
+ public void afterTestExecution(AfterTestExecutionEvent e) throws Exception {
+ trigger().afterTestExecution(e.getSource());
+ }
+
+ @AfterTestMethod
+ public void afterTestMethod(AfterTestMethodEvent e) throws Exception {
+ trigger().afterTestMethod(e.getSource());
+ }
+
+ @AfterTestClass
+ public void afterTestClass(AfterTestClassEvent e) throws Exception {
+ trigger().afterTestClass(e.getSource());
+ }
+
+ }
+
+ @ContextConfiguration(classes = EventCaptureConfiguration.class)
+ @TestExecutionListeners(EventPublishingTestExecutionListener.class)
+ static class EmptyTestCase {
+
+ /**
+ * Serves as dummy test method.
+ */
+ @SuppressWarnings("PMD.UncommentedEmptyMethodBody")
+ public void dummyTestMethod() {
+ }
+ }
+
+ static class TestContextExposingTestContextManager extends TestContextManager {
+ public TestContextExposingTestContextManager() {
+ super(EmptyTestCase.class);
+ }
+
+ public TestContext getProtectedTestContext() {
+ return getTestContext();
+ }
+ }
+
+ @Before
+ public void initialize() {
+ TestContextExposingTestContextManager tcm = new TestContextExposingTestContextManager();
+ testContextManager = tcm;
+ testContext = tcm.getProtectedTestContext();
+ trigger = testContext.getApplicationContext().getBean(EventCaptureConfiguration.class).trigger();
+ // reset because mock is a cached context bean
+ reset(trigger);
+ testInstance = new EmptyTestCase();
+ testMethod = ReflectionUtils.findMethod(EmptyTestCase.class, "dummyMethod");
+ }
+
+ @Test
+ public void beforeTestClassAnnotation() throws Exception {
+ testContextManager.beforeTestClass();
+ verify(trigger, only()).beforeTestClass(testContext);
+ }
+
+ @Test
+ public void prepareTestInstanceAnnotation() throws Exception {
+ testContextManager.prepareTestInstance(testInstance);
+ verify(trigger, only()).prepareTestInstance(testContext);
+ }
+
+ @Test
+ public void beforeTestMethodAnnotation() throws Exception {
+ testContextManager.beforeTestMethod(testInstance, testMethod);
+ verify(trigger, only()).beforeTestMethod(testContext);
+ }
+
+ @Test
+ public void beforeTestExecutionAnnotation() throws Exception {
+ testContextManager.beforeTestExecution(testInstance, testMethod);
+ verify(trigger, only()).beforeTestExecution(testContext);
+ }
+
+ @Test
+ public void afterTestExecutionAnnotation() throws Exception {
+ testContextManager.afterTestExecution(testInstance, testMethod, null);
+ verify(trigger, only()).afterTestExecution(testContext);
+ }
+
+ @Test
+ public void afterTestMethodAnnotation() throws Exception {
+ testContextManager.afterTestMethod(testInstance, testMethod, null);
+ verify(trigger, only()).afterTestMethod(testContext);
+ }
+
+ @Test
+ public void afterTestClassAnnotation() throws Exception {
+ testContextManager.afterTestClass();
+ verify(trigger, only()).afterTestClass(testContext);
+ }
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerTests.java
new file mode 100644
index 000000000000..f803dec7c919
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/event/EventPublishingTestExecutionListenerTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2019 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.event;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.context.TestContext;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.mockito.BDDMockito.only;
+import static org.mockito.BDDMockito.verify;
+
+
+/**
+ * Unit test for {@link EventPublishingTestExecutionListener}.
+ *
+ * @author Frank Scheffler
+ * @since 5.2
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class EventPublishingTestExecutionListenerTests {
+
+ @Mock(answer=Answers.RETURNS_DEEP_STUBS)
+ private TestContext testContext;
+
+ @Captor
+ private ArgumentCaptor