Improve documentation for TestContext events
This commit improves the documentation for test execution events, especially with regard to the fact that, by default, a BeforeTestClassEvent is not published for the first test class using a particular ApplicationContext. This commit also introduces tests that verify the default behavior and the ability to change the default behavior with a custom TestExecutionListener that eagerly loads the context. Closes gh-27757
This commit is contained in:
		
							parent
							
								
									8cbb188455
								
							
						
					
					
						commit
						a2f02dbfc0
					
				| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -17,16 +17,12 @@
 | 
				
			||||||
package org.springframework.test.context.event;
 | 
					package org.springframework.test.context.event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.test.context.TestContext;
 | 
					import org.springframework.test.context.TestContext;
 | 
				
			||||||
import org.springframework.test.context.TestExecutionListener;
 | 
					 | 
				
			||||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
 | 
					import org.springframework.test.context.support.AbstractTestExecutionListener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListener TestExecutionListener}
 | 
					 * {@code TestExecutionListener} that publishes test execution events to the
 | 
				
			||||||
 * that publishes test execution events to the
 | 
					 | 
				
			||||||
 * {@link org.springframework.context.ApplicationContext ApplicationContext}
 | 
					 * {@link org.springframework.context.ApplicationContext ApplicationContext}
 | 
				
			||||||
 * for the currently executing test. Events are only published if the
 | 
					 * for the currently executing test.
 | 
				
			||||||
 * {@code ApplicationContext} {@linkplain TestContext#hasApplicationContext()
 | 
					 | 
				
			||||||
 * has already been loaded}.
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <h3>Supported Events</h3>
 | 
					 * <h3>Supported Events</h3>
 | 
				
			||||||
 * <ul>
 | 
					 * <ul>
 | 
				
			||||||
| 
						 | 
					@ -41,11 +37,33 @@ import org.springframework.test.context.support.AbstractTestExecutionListener;
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <p>These events may be consumed for various reasons, such as resetting <em>mock</em>
 | 
					 * <p>These events may be consumed for various reasons, such as resetting <em>mock</em>
 | 
				
			||||||
 * beans or tracing test execution. One advantage of consuming test events rather
 | 
					 * beans or tracing test execution. One advantage of consuming test events rather
 | 
				
			||||||
 * than implementing a custom {@link TestExecutionListener} is that test events
 | 
					 * than implementing a custom {@link org.springframework.test.context.TestExecutionListener
 | 
				
			||||||
 * may be consumed by any Spring bean registered in the test {@code ApplicationContext},
 | 
					 * TestExecutionListener} is that test events may be consumed by any Spring bean
 | 
				
			||||||
 * and such beans may benefit directly from dependency injection and other features
 | 
					 * registered in the test {@code ApplicationContext}, and such beans may benefit
 | 
				
			||||||
 * of the {@code ApplicationContext}. In contrast, a {@link TestExecutionListener}
 | 
					 * directly from dependency injection and other features of the {@code ApplicationContext}.
 | 
				
			||||||
 * is not a bean in the {@code ApplicationContext}.
 | 
					 * In contrast, a {@code TestExecutionListener} is not a bean in the {@code ApplicationContext}.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * <p>Note that the {@code EventPublishingTestExecutionListener} is registered by
 | 
				
			||||||
 | 
					 * default; however, it only publishes events if the {@code ApplicationContext}
 | 
				
			||||||
 | 
					 * {@linkplain TestContext#hasApplicationContext() has already been loaded}. This
 | 
				
			||||||
 | 
					 * prevents the {@code ApplicationContext} from being loaded unnecessarily or too
 | 
				
			||||||
 | 
					 * early. Consequently, a {@code BeforeTestClassEvent} will not be published until
 | 
				
			||||||
 | 
					 * after the {@code ApplicationContext} has been loaded by another
 | 
				
			||||||
 | 
					 * {@code TestExecutionListener}. For example, with the default set of
 | 
				
			||||||
 | 
					 * {@code TestExecutionListeners} registered, a {@code BeforeTestClassEvent} will
 | 
				
			||||||
 | 
					 * not be published for the first test class that uses a particular test
 | 
				
			||||||
 | 
					 * {@code ApplicationContext}, but a {@code BeforeTestClassEvent} will be published
 | 
				
			||||||
 | 
					 * for any subsequent test class in the same test suite that uses the same test
 | 
				
			||||||
 | 
					 * {@code ApplicationContext} since the context will already have been loaded
 | 
				
			||||||
 | 
					 * when subsequent test classes run (as long as the context has not been removed
 | 
				
			||||||
 | 
					 * from the {@link org.springframework.test.context.cache.ContextCache ContextCache}
 | 
				
			||||||
 | 
					 * via {@link org.springframework.test.annotation.DirtiesContext @DirtiesContext}
 | 
				
			||||||
 | 
					 * or the max-size eviction policy). If you wish to ensure that a
 | 
				
			||||||
 | 
					 * {@code BeforeTestClassEvent} is published for every test class, you need to
 | 
				
			||||||
 | 
					 * register a {@code TestExecutionListener} that loads the {@code ApplicationContext}
 | 
				
			||||||
 | 
					 * in the {@link org.springframework.test.context.TestExecutionListener#beforeTestClass
 | 
				
			||||||
 | 
					 * beforeTestClass} callback, and that {@code TestExecutionListener} must be registered
 | 
				
			||||||
 | 
					 * before the {@code EventPublishingTestExecutionListener}.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <h3>Exception Handling</h3>
 | 
					 * <h3>Exception Handling</h3>
 | 
				
			||||||
 * <p>By default, if a test event listener throws an exception while consuming
 | 
					 * <p>By default, if a test event listener throws an exception while consuming
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2019 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 | 
				
			||||||
 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
					 * <p>The {@code EventPublishingTestExecutionListener} must be registered in order
 | 
				
			||||||
 * for this annotation to have an effect — for example, via
 | 
					 * for this annotation to have an effect — for example, via
 | 
				
			||||||
 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
					 * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}.
 | 
				
			||||||
 | 
					 * Note, however, that the {@code EventPublishingTestExecutionListener} is registered
 | 
				
			||||||
 | 
					 * by default.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Frank Scheffler
 | 
					 * @author Frank Scheffler
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Test event annotations for the <em>Spring TestContext Framework</em>.
 | 
					 * Test execution event annotations for the <em>Spring TestContext Framework</em>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
package org.springframework.test.context.event.annotation;
 | 
					package org.springframework.test.context.event.annotation;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,190 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2002-2022 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
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      https://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.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.AfterEach;
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.BeforeEach;
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test;
 | 
				
			||||||
 | 
					import org.junit.platform.testkit.engine.EngineTestKit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Configuration;
 | 
				
			||||||
 | 
					import org.springframework.core.annotation.Order;
 | 
				
			||||||
 | 
					import org.springframework.test.context.TestContext;
 | 
				
			||||||
 | 
					import org.springframework.test.context.TestExecutionListener;
 | 
				
			||||||
 | 
					import org.springframework.test.context.TestExecutionListeners;
 | 
				
			||||||
 | 
					import org.springframework.test.context.TestExecutionListeners.MergeMode;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.AfterTestClass;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.AfterTestExecution;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.AfterTestMethod;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.BeforeTestClass;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.BeforeTestExecution;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.BeforeTestMethod;
 | 
				
			||||||
 | 
					import org.springframework.test.context.event.annotation.PrepareTestInstance;
 | 
				
			||||||
 | 
					import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
 | 
					import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tests for the {@link EventPublishingTestExecutionListener} which verify that
 | 
				
			||||||
 | 
					 * a {@link BeforeTestClassEvent} can be eagerly published; whereas, such an
 | 
				
			||||||
 | 
					 * event is not published by default for the first run of a test class for a
 | 
				
			||||||
 | 
					 * specific {@code ApplicationContext}.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author Sam Brannen
 | 
				
			||||||
 | 
					 * @since 5.3.17
 | 
				
			||||||
 | 
					 * @see https://github.com/spring-projects/spring-framework/issues/27757
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class EagerTestExecutionEventPublishingTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final List<Class<? extends TestContextEvent>> events = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@BeforeEach
 | 
				
			||||||
 | 
						@AfterEach
 | 
				
			||||||
 | 
						void resetEvents() {
 | 
				
			||||||
 | 
							events.clear();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						void beforeTestClassEventIsNotPublishedByDefaultForFirstTestClass() {
 | 
				
			||||||
 | 
							EngineTestKit.engine("junit-jupiter")//
 | 
				
			||||||
 | 
									.selectors(selectClass(LazyTestCase1.class), selectClass(LazyTestCase2.class))//
 | 
				
			||||||
 | 
									.execute()//
 | 
				
			||||||
 | 
									.testEvents()//
 | 
				
			||||||
 | 
									.assertStatistics(stats -> stats.started(2).succeeded(2).failed(0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assertThat(events).containsExactly(//
 | 
				
			||||||
 | 
								// 1st test class
 | 
				
			||||||
 | 
								// BeforeTestClassEvent.class -- missing for 1st test class
 | 
				
			||||||
 | 
								PrepareTestInstanceEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestMethodEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestMethodEvent.class, //
 | 
				
			||||||
 | 
								AfterTestClassEvent.class, //
 | 
				
			||||||
 | 
								// 2nd test class
 | 
				
			||||||
 | 
								BeforeTestClassEvent.class, //
 | 
				
			||||||
 | 
								PrepareTestInstanceEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestMethodEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestMethodEvent.class, //
 | 
				
			||||||
 | 
								AfterTestClassEvent.class//
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						void beforeTestClassEventIsPublishedForAllTestClassesIfCustomListenerEagerlyLoadsContext() {
 | 
				
			||||||
 | 
							EngineTestKit.engine("junit-jupiter")//
 | 
				
			||||||
 | 
									.selectors(selectClass(EagerTestCase1.class), selectClass(EagerTestCase2.class))//
 | 
				
			||||||
 | 
									.execute()//
 | 
				
			||||||
 | 
									.testEvents()//
 | 
				
			||||||
 | 
									.assertStatistics(stats -> stats.started(2).succeeded(2).failed(0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assertThat(events).containsExactly(//
 | 
				
			||||||
 | 
								// 1st test class
 | 
				
			||||||
 | 
								BeforeTestClassEvent.class, //
 | 
				
			||||||
 | 
								PrepareTestInstanceEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestMethodEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestMethodEvent.class, //
 | 
				
			||||||
 | 
								AfterTestClassEvent.class, //
 | 
				
			||||||
 | 
								// 2nd test class
 | 
				
			||||||
 | 
								BeforeTestClassEvent.class, //
 | 
				
			||||||
 | 
								PrepareTestInstanceEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestMethodEvent.class, //
 | 
				
			||||||
 | 
								BeforeTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestExecutionEvent.class, //
 | 
				
			||||||
 | 
								AfterTestMethodEvent.class, //
 | 
				
			||||||
 | 
								AfterTestClassEvent.class//
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@SpringJUnitConfig(Config.class)
 | 
				
			||||||
 | 
						static class LazyTestCase1 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Test
 | 
				
			||||||
 | 
							void test() {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static class LazyTestCase2 extends LazyTestCase1 {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@TestExecutionListeners(listeners = EagerLoadingTestExecutionListener.class, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
 | 
				
			||||||
 | 
						static class EagerTestCase1 extends LazyTestCase1 {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static class EagerTestCase2 extends EagerTestCase1 {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Configuration
 | 
				
			||||||
 | 
						static class Config {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@BeforeTestClass
 | 
				
			||||||
 | 
							public void beforeTestClass(BeforeTestClassEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@PrepareTestInstance
 | 
				
			||||||
 | 
							public void prepareTestInstance(PrepareTestInstanceEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@BeforeTestMethod
 | 
				
			||||||
 | 
							public void beforeTestMethod(BeforeTestMethodEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@BeforeTestExecution
 | 
				
			||||||
 | 
							public void beforeTestExecution(BeforeTestExecutionEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@AfterTestExecution
 | 
				
			||||||
 | 
							public void afterTestExecution(AfterTestExecutionEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@AfterTestMethod
 | 
				
			||||||
 | 
							public void afterTestMethod(AfterTestMethodEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@AfterTestClass
 | 
				
			||||||
 | 
							public void afterTestClass(AfterTestClassEvent e) {
 | 
				
			||||||
 | 
								events.add(e.getClass());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Order(0)
 | 
				
			||||||
 | 
						static class EagerLoadingTestExecutionListener implements TestExecutionListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Override
 | 
				
			||||||
 | 
							public void beforeTestClass(TestContext testContext) {
 | 
				
			||||||
 | 
								testContext.getApplicationContext();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2672,8 +2672,6 @@ test's `ApplicationContext` can listen to the following events published by the
 | 
				
			||||||
* `AfterTestMethodEvent`
 | 
					* `AfterTestMethodEvent`
 | 
				
			||||||
* `AfterTestClassEvent`
 | 
					* `AfterTestClassEvent`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NOTE: These events are only published if the `ApplicationContext` has already been loaded.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
These events may be consumed for various reasons, such as resetting mock beans or tracing
 | 
					These events may be consumed for various reasons, such as resetting mock beans or tracing
 | 
				
			||||||
test execution. One advantage of consuming test execution events rather than implementing
 | 
					test execution. One advantage of consuming test execution events rather than implementing
 | 
				
			||||||
a custom `TestExecutionListener` is that test execution events may be consumed by any
 | 
					a custom `TestExecutionListener` is that test execution events may be consumed by any
 | 
				
			||||||
| 
						 | 
					@ -2681,6 +2679,28 @@ Spring bean registered in the test `ApplicationContext`, and such beans may bene
 | 
				
			||||||
directly from dependency injection and other features of the `ApplicationContext`. In
 | 
					directly from dependency injection and other features of the `ApplicationContext`. In
 | 
				
			||||||
contrast, a `TestExecutionListener` is not a bean in the `ApplicationContext`.
 | 
					contrast, a `TestExecutionListener` is not a bean in the `ApplicationContext`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[NOTE]
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					The `EventPublishingTestExecutionListener` is registered by default; however, it only
 | 
				
			||||||
 | 
					publishes events if the `ApplicationContext` has _already been loaded_. This prevents the
 | 
				
			||||||
 | 
					`ApplicationContext` from being loaded unnecessarily or too early.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consequently, a `BeforeTestClassEvent` will not be published until after the
 | 
				
			||||||
 | 
					`ApplicationContext` has been loaded by another `TestExecutionListener`. For example, with
 | 
				
			||||||
 | 
					the default set of `TestExecutionListener` implementations registered, a
 | 
				
			||||||
 | 
					`BeforeTestClassEvent` will not be published for the first test class that uses a
 | 
				
			||||||
 | 
					particular test `ApplicationContext`, but a `BeforeTestClassEvent` _will_ be published for
 | 
				
			||||||
 | 
					any subsequent test class in the same test suite that uses the same test
 | 
				
			||||||
 | 
					`ApplicationContext` since the context will already have been loaded when subsequent test
 | 
				
			||||||
 | 
					classes run (as long as the context has not been removed from the `ContextCache` via
 | 
				
			||||||
 | 
					`@DirtiesContext` or the max-size eviction policy).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you wish to ensure that a `BeforeTestClassEvent` is always published for every test
 | 
				
			||||||
 | 
					class, you need to register a `TestExecutionListener` that loads the `ApplicationContext`
 | 
				
			||||||
 | 
					in the `beforeTestClass` callback, and that `TestExecutionListener` must be registered
 | 
				
			||||||
 | 
					_before_ the `EventPublishingTestExecutionListener`.
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In order to listen to test execution events, a Spring bean may choose to implement the
 | 
					In order to listen to test execution events, a Spring bean may choose to implement the
 | 
				
			||||||
`org.springframework.context.ApplicationListener` interface. Alternatively, listener
 | 
					`org.springframework.context.ApplicationListener` interface. Alternatively, listener
 | 
				
			||||||
methods can be annotated with `@EventListener` and configured to listen to one of the
 | 
					methods can be annotated with `@EventListener` and configured to listen to one of the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue