Fix logic for validating @RecordApplicationEvents config
Prior to this commit, the SpringExtension looked up the TestInstance.Lifecycle and ExecutionMode using TestContextAnnotationUtils; however, using TestContextAnnotationUtils is problematic since the TestInstance.Lifecycle and ExecutionMode can be configured globally via configuration parameters instead of locally via the @TestInstance and @Execution annotations. This commit addresses these issues by looking up the TestInstance.Lifecycle and ExecutionMode via JUnit Jupiter's ExtensionContext which takes into account both global and local configuration. See gh-30020
This commit is contained in:
@@ -32,8 +32,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.junit.jupiter.api.parallel.Execution;
|
||||
import org.junit.jupiter.api.parallel.ExecutionMode;
|
||||
import org.junit.platform.engine.TestExecutionResult;
|
||||
import org.junit.platform.testkit.engine.EngineExecutionResults;
|
||||
import org.junit.platform.testkit.engine.EngineTestKit;
|
||||
@@ -68,28 +66,27 @@ class ParallelApplicationEventsIntegrationTests {
|
||||
void rejectTestsInParallelWithInstancePerClassAndRecordApplicationEvents() {
|
||||
Class<?> testClass = TestInstancePerClassTestCase.class;
|
||||
|
||||
final EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
|
||||
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
|
||||
.selectors(selectClass(testClass))//
|
||||
.configurationParameter("junit.jupiter.execution.parallel.enabled", "true")//
|
||||
.configurationParameter("junit.jupiter.execution.parallel.mode.default", "concurrent")//
|
||||
.configurationParameter("junit.jupiter.execution.parallel.config.dynamic.factor", "10")//
|
||||
.execute();
|
||||
|
||||
//extract the messages from failed TextExecutionResults
|
||||
// extract the messages from failed TextExecutionResults
|
||||
assertThat(results.containerEvents().failed()//
|
||||
.stream().map(e -> e.getRequiredPayload(TestExecutionResult.class)//
|
||||
.getThrowable().get().getMessage()))//
|
||||
.map(e -> e.getRequiredPayload(TestExecutionResult.class).getThrowable().get().getMessage()))//
|
||||
.singleElement(InstanceOfAssertFactories.STRING)
|
||||
.isEqualToIgnoringNewLines("""
|
||||
Test classes or inner classes that @RecordApplicationEvents\s
|
||||
must not be run in parallel with the @TestInstance(Lifecycle.PER_CLASS) configuration.\s
|
||||
Use either @Execution(SAME_THREAD), @TestInstance(PER_METHOD) or disable parallel\s
|
||||
execution altogether. Note that when recording events in parallel, one might see events\s
|
||||
published by other tests as the application context can be common.
|
||||
""");
|
||||
.isEqualTo("""
|
||||
Test classes or @Nested test classes that @RecordApplicationEvents must not be run \
|
||||
in parallel with the @TestInstance(PER_CLASS) lifecycle mode. Configure either \
|
||||
@Execution(SAME_THREAD) or @TestInstance(PER_METHOD) semantics, or disable parallel \
|
||||
execution altogether. Note that when recording events in parallel, one might see events \
|
||||
published by other tests since the application context may be shared.""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void executeTestsInParallelInstancePerMethod() {
|
||||
void executeTestsInParallelWithInstancePerMethod() {
|
||||
Class<?> testClass = TestInstancePerMethodTestCase.class;
|
||||
Events testEvents = EngineTestKit.engine("junit-jupiter")//
|
||||
.selectors(selectClass(testClass))//
|
||||
@@ -97,7 +94,7 @@ class ParallelApplicationEventsIntegrationTests {
|
||||
.configurationParameter("junit.jupiter.execution.parallel.config.dynamic.factor", "10")//
|
||||
.execute()//
|
||||
.testEvents();
|
||||
//list failed events in case of test errors to get a sense of which tests failed
|
||||
// list failed events in case of test errors to get a sense of which tests failed
|
||||
Events failedTests = testEvents.failed();
|
||||
if (failedTests.count() > 0) {
|
||||
failedTests.debug();
|
||||
@@ -141,7 +138,6 @@ class ParallelApplicationEventsIntegrationTests {
|
||||
|
||||
@SpringJUnitConfig
|
||||
@RecordApplicationEvents
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
@TestInstance(Lifecycle.PER_METHOD)
|
||||
static class TestInstancePerMethodTestCase {
|
||||
|
||||
@@ -211,7 +207,7 @@ class ParallelApplicationEventsIntegrationTests {
|
||||
|
||||
@Test
|
||||
void asyncPublication(ApplicationEvents events) throws InterruptedException {
|
||||
final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
executorService.execute(() -> this.context.publishEvent("asyncPublication"));
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(10, TimeUnit.SECONDS);
|
||||
|
||||
Reference in New Issue
Block a user