mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-21 21:39:05 +00:00
Avoid unnecessary pausing of application contexts for tests
In commit 9711db787e, we introduced support for disabling test
application context pausing via a Spring property or JVM system
property, as follows.
-Dspring.test.context.cache.pause=never
However, users may actually be interested in keeping the pausing
feature enabled if contexts are not paused unnecessarily.
To address that, this commit introduces a new
PauseMode.ON_CONTEXT_SWITCH enum constant which is now used by default
in the DefaultContextCache.
With this new pause mode, an unused application context will no longer
be paused immediately. Instead, an unused application context will be
paused lazily the first time a different context is retrieved from or
stored in the ContextCache. This effectively means that an unused
context will not be paused at all if the next test class uses the same
context.
Although ON_CONTEXT_SWITCH is the now the default pause mode, users
still have the option to enable context pausing for all usage scenarios
(not only context switches) by setting the Spring property or JVM
system property to ALWAYS (case insensitive) — for example:
-Dspring.test.context.cache.pause=always
This commit also introduces a dedicated "Context Pausing" section in
the reference manual.
See gh-36117
Closes gh-36044
This commit is contained in:
Vendored
+49
@@ -103,6 +103,55 @@ class ContextCachePauseModeTests {
|
||||
clearApplicationEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
void topLevelTestClassesWithPauseModeOnContextSwitch() {
|
||||
this.contextCache = new DefaultContextCache(DEFAULT_MAX_CONTEXT_CACHE_SIZE, PauseMode.ON_CONTEXT_SWITCH);
|
||||
|
||||
loadCtxAndAssertStats(TestCase1A.class, 1, 1, 0, 1);
|
||||
assertThat(EventTracker.events).containsExactly("ContextRefreshed:TestCase1A");
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase1A.class, 1, 1, 1, 1);
|
||||
assertThat(EventTracker.events).isEmpty();
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase1B.class, 1, 1, 2, 1);
|
||||
assertThat(EventTracker.events).isEmpty();
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase1A.class, 1, 1, 3, 1);
|
||||
assertThat(EventTracker.events).isEmpty();
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase2.class, 2, 1, 3, 2);
|
||||
assertThat(EventTracker.events).containsExactly("ContextPaused:TestCase1A", "ContextRefreshed:TestCase2");
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase1B.class, 2, 1, 4, 2);
|
||||
assertThat(EventTracker.events).containsExactly("ContextPaused:TestCase2", "ContextRestarted:TestCase1A");
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase1A.class, 2, 1, 5, 2);
|
||||
assertThat(EventTracker.events).isEmpty();
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase2.class, 2, 1, 6, 2);
|
||||
assertThat(EventTracker.events).containsExactly("ContextPaused:TestCase1A", "ContextRestarted:TestCase2");
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase2.class, 2, 1, 7, 2);
|
||||
assertThat(EventTracker.events).isEmpty();
|
||||
clearApplicationEvents();
|
||||
|
||||
markContextDirty(TestCase2.class);
|
||||
assertThat(EventTracker.events).containsExactly("ContextClosed:TestCase2");
|
||||
clearApplicationEvents();
|
||||
|
||||
loadCtxAndAssertStats(TestCase2.class, 2, 1, 7, 3);
|
||||
assertThat(EventTracker.events).containsExactly("ContextRefreshed:TestCase2");
|
||||
clearApplicationEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
void topLevelTestClassesWithPauseModeNever() {
|
||||
this.contextCache = new DefaultContextCache(DEFAULT_MAX_CONTEXT_CACHE_SIZE, PauseMode.NEVER);
|
||||
|
||||
Vendored
+22
-1
@@ -112,6 +112,13 @@ class ContextCacheUtilsTests {
|
||||
"\talways\u000B"
|
||||
};
|
||||
|
||||
static final String[] ON_CONTEXT_SWITCH_VALUES = {
|
||||
"on_context_switch",
|
||||
"On_Context_Switch",
|
||||
"ON_CONTEXT_SWITCH",
|
||||
"\ton_context_switch\u000B"
|
||||
};
|
||||
|
||||
static final String[] NEVER_VALUES = {
|
||||
"never",
|
||||
"Never",
|
||||
@@ -129,7 +136,7 @@ class ContextCacheUtilsTests {
|
||||
|
||||
@Test
|
||||
void retrievePauseModeFromDefault() {
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ALWAYS);
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ON_CONTEXT_SWITCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -151,6 +158,13 @@ class ContextCacheUtilsTests {
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ALWAYS);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@FieldSource("ON_CONTEXT_SWITCH_VALUES")
|
||||
void retrievePauseModeFromSystemPropertyWithValueOnContextSwitch(String value) {
|
||||
System.setProperty(CONTEXT_CACHE_PAUSE_PROPERTY_NAME, value);
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ON_CONTEXT_SWITCH);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@FieldSource("NEVER_VALUES")
|
||||
void retrievePauseModeFromSystemPropertyWithValueNever(String value) {
|
||||
@@ -165,6 +179,13 @@ class ContextCacheUtilsTests {
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ALWAYS);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@FieldSource("ON_CONTEXT_SWITCH_VALUES")
|
||||
void retrievePauseModeFromSpringPropertyWithValueOnContextSwitch(String value) {
|
||||
SpringProperties.setProperty(CONTEXT_CACHE_PAUSE_PROPERTY_NAME, value);
|
||||
assertThat(retrievePauseMode()).isEqualTo(PauseMode.ON_CONTEXT_SWITCH);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@FieldSource("NEVER_VALUES")
|
||||
void retrievePauseModeFromSpringPropertyWithValueNever(String value) {
|
||||
|
||||
spring-test/src/test/java/org/springframework/test/context/cache/UnusedContextsIntegrationTests.java
Vendored
+222
-49
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.test.context.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.ClassOrderer;
|
||||
@@ -23,20 +27,26 @@ import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestClassOrder;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.junit.platform.testkit.engine.EngineTestKit;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextCustomizerFactories;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.cache.ContextCache.PauseMode;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
|
||||
import static org.springframework.test.context.cache.ContextCacheTestUtils.resetContextCache;
|
||||
|
||||
/**
|
||||
* Integration tests for pausing and restarting "unused" contexts.
|
||||
@@ -49,10 +59,63 @@ class UnusedContextsIntegrationTests {
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void clearApplicationEvents() {
|
||||
void clearApplicationEventsAndResetContextCache() {
|
||||
resetContextCache();
|
||||
EventTracker.events.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void topLevelTestClassesWithDifferentApplicationContexts() {
|
||||
runTestClasses(6,
|
||||
TestCaseConfig1A.class,
|
||||
TestCaseConfig1B.class,
|
||||
TestCaseConfig2.class,
|
||||
TestCaseConfig3.class,
|
||||
TestCaseConfig4.class,
|
||||
TestCaseConfig5.class);
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
|
||||
// --- TestCaseConfig1A --------------------------------------------
|
||||
"ContextRefreshed:TestCaseConfig1A",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCaseConfig1A",
|
||||
|
||||
// --- TestCaseConfig1B --------------------------------------------
|
||||
// Here we expect a BeforeTestClass event, since TestCaseConfig1B
|
||||
// uses the same context as TestCaseConfig1A.
|
||||
"BeforeTestClass:TestCaseConfig1B",
|
||||
"AfterTestClass:TestCaseConfig1B",
|
||||
|
||||
// --- TestCaseConfig2 ---------------------------------------------
|
||||
"ContextPaused:TestCaseConfig1A",
|
||||
"ContextRefreshed:TestCaseConfig2",
|
||||
"AfterTestClass:TestCaseConfig2",
|
||||
|
||||
// --- TestCaseConfig3 ---------------------------------------------
|
||||
"ContextPaused:TestCaseConfig2",
|
||||
"ContextRefreshed:TestCaseConfig3",
|
||||
"AfterTestClass:TestCaseConfig3",
|
||||
// Closed instead of Paused, since TestCaseConfig3 uses @DirtiesContext
|
||||
"ContextClosed:TestCaseConfig3",
|
||||
|
||||
// --- TestCaseConfig4 ---------------------------------------------
|
||||
"ContextRefreshed:TestCaseConfig4",
|
||||
"AfterTestClass:TestCaseConfig4",
|
||||
|
||||
// --- TestCaseConfig5 ---------------------------------------------
|
||||
"ContextPaused:TestCaseConfig4",
|
||||
"ContextRefreshed:TestCaseConfig5",
|
||||
"AfterTestClass:TestCaseConfig5"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since {@link PauseMode#ON_CONTEXT_SWITCH} is now the default, there are
|
||||
* no {@code ContextPausedEvent} or {@code ContextRestartedEvent} events
|
||||
* when all test classes share the same context.
|
||||
*/
|
||||
@Test
|
||||
void topLevelTestClassesWithSharedApplicationContext() {
|
||||
runTestClasses(5, TestCase1.class, TestCase2.class, TestCase3.class, TestCase4.class, TestCase5.class);
|
||||
@@ -60,58 +123,63 @@ class UnusedContextsIntegrationTests {
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
|
||||
// --- TestCase1 -----------------------------------------------
|
||||
// Refreshed instead of Restarted, since this is the first time
|
||||
// the context is loaded.
|
||||
// Refreshed, since this is the first time the context is loaded.
|
||||
"ContextRefreshed:TestCase1",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCase1",
|
||||
"ContextPaused:TestCase1",
|
||||
|
||||
// --- TestCase2 -----------------------------------------------
|
||||
"ContextRestarted:TestCase1",
|
||||
"BeforeTestClass:TestCase2",
|
||||
"AfterTestClass:TestCase2",
|
||||
"ContextPaused:TestCase1",
|
||||
|
||||
// --- TestCase3 -----------------------------------------------
|
||||
"ContextRestarted:TestCase1",
|
||||
"BeforeTestClass:TestCase3",
|
||||
"AfterTestClass:TestCase3",
|
||||
// Closed instead of Stopped, since TestCase3 uses @DirtiesContext
|
||||
// Closed instead of Paused, since TestCase3 uses @DirtiesContext
|
||||
"ContextClosed:TestCase1",
|
||||
|
||||
// --- TestCase4 -----------------------------------------------
|
||||
// Refreshed instead of Restarted, since TestCase3 uses @DirtiesContext
|
||||
// Refreshed, since TestCase3 uses @DirtiesContext
|
||||
"ContextRefreshed:TestCase4",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCase4",
|
||||
"ContextPaused:TestCase4",
|
||||
|
||||
// --- TestCase5 -----------------------------------------------
|
||||
"ContextRestarted:TestCase4",
|
||||
"BeforeTestClass:TestCase5",
|
||||
"AfterTestClass:TestCase5",
|
||||
"ContextPaused:TestCase4"
|
||||
"AfterTestClass:TestCase5"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassesInNestedTestHierarchy() {
|
||||
runTestClasses(5, EnclosingTestCase.class);
|
||||
testClassesInNestedTestHierarchy(EnclosingTestCase.class, false);
|
||||
}
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
@Test
|
||||
void testClassesInNestedTestHierarchyWithTestInstanceLifecyclePerClass() {
|
||||
testClassesInNestedTestHierarchy(TestInstancePerClassEnclosingTestCase.class, true);
|
||||
}
|
||||
|
||||
private void testClassesInNestedTestHierarchy(Class<?> enclosingClass, boolean expectBeforeTestClassEvent) {
|
||||
// We also run a stand-alone top-level test class after the nested hierarchy,
|
||||
// in order to verify what happens for a context switch from a nested hierarchy
|
||||
// to something else.
|
||||
runTestClasses(7, enclosingClass, TestCase1.class);
|
||||
|
||||
String enclosingClassName = enclosingClass.getSimpleName();
|
||||
|
||||
String[] events = {
|
||||
// --- EnclosingTestCase -------------------------------------------
|
||||
"ContextRefreshed:EnclosingTestCase",
|
||||
"ContextRefreshed:" + enclosingClassName,
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
|
||||
// --- NestedTestCase ------------------------------------------
|
||||
// No Refreshed or Restarted event, since NestedTestCase shares the
|
||||
// --- NestedTestCase1 -----------------------------------------
|
||||
// No Refreshed or Restarted event, since NestedTestCase1 shares the
|
||||
// active context used by EnclosingTestCase.
|
||||
"BeforeTestClass:NestedTestCase",
|
||||
"BeforeTestClass:NestedTestCase1",
|
||||
|
||||
// --- OverridingNestedTestCase1 ---------------------------
|
||||
"ContextRefreshed:OverridingNestedTestCase1",
|
||||
@@ -123,34 +191,64 @@ class UnusedContextsIntegrationTests {
|
||||
// shares the active context used by OverridingNestedTestCase1.
|
||||
"BeforeTestClass:InheritingNestedTestCase",
|
||||
"AfterTestClass:InheritingNestedTestCase",
|
||||
// No Stopped event, since OverridingNestedTestCase1 is still
|
||||
// No Paused event, since OverridingNestedTestCase1 is still
|
||||
// using the context
|
||||
|
||||
"AfterTestClass:OverridingNestedTestCase1",
|
||||
"ContextPaused:OverridingNestedTestCase1",
|
||||
// No Paused event, since OverridingNestedTestCase2 will reuse
|
||||
// the context
|
||||
|
||||
// --- OverridingNestedTestCase2 ---------------------------
|
||||
"ContextRestarted:OverridingNestedTestCase1",
|
||||
// No Restarted event, since OverridingNestedTestCase2 will reuse
|
||||
// the context
|
||||
"BeforeTestClass:OverridingNestedTestCase2",
|
||||
"AfterTestClass:OverridingNestedTestCase2",
|
||||
"ContextPaused:OverridingNestedTestCase1",
|
||||
|
||||
"AfterTestClass:NestedTestCase",
|
||||
// No Stopped event, since EnclosingTestCase is still using the context
|
||||
"AfterTestClass:NestedTestCase1",
|
||||
// No Paused event, since EnclosingTestCase is still using the context
|
||||
|
||||
"AfterTestClass:EnclosingTestCase",
|
||||
"ContextPaused:EnclosingTestCase"
|
||||
);
|
||||
// --- NestedTestCase2 -----------------------------------------
|
||||
// Refreshed, since this is the first time the context is loaded.
|
||||
"ContextRefreshed:NestedTestCase2",
|
||||
"AfterTestClass:NestedTestCase2",
|
||||
|
||||
// Paused, since the context used by NestedTestCase2 is no longer used,
|
||||
// and EventPublishingTestExecutionListener.afterTestClass() "gets" the
|
||||
// context for the enclosing class again, which constitutes a context switch.
|
||||
"ContextPaused:NestedTestCase2",
|
||||
"AfterTestClass:" + enclosingClassName,
|
||||
|
||||
// --- TestCase1 ---------------------------------------------------
|
||||
// Paused, since the context for the enclosing class is no longer used.
|
||||
"ContextPaused:" + enclosingClassName,
|
||||
// Refreshed, since this is the first time the context is loaded.
|
||||
"ContextRefreshed:TestCase1",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCase1",
|
||||
};
|
||||
|
||||
List<String> eventsList = new ArrayList<>();
|
||||
Collections.addAll(eventsList, events);
|
||||
if (expectBeforeTestClassEvent) {
|
||||
eventsList.add(1, "BeforeTestClass:" + enclosingClassName);
|
||||
}
|
||||
assertThat(EventTracker.events).containsExactlyElementsOf(eventsList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassesWithContextHierarchies() {
|
||||
runTestClasses(5,
|
||||
// We also run a stand-alone top-level test class after the context hierarchy,
|
||||
// in order to verify what happens for a context switch from a context hierarchy
|
||||
// to something else.
|
||||
runTestClasses(6,
|
||||
ContextHierarchyLevel1TestCase.class,
|
||||
ContextHierarchyLevel2TestCase.class,
|
||||
ContextHierarchyLevel3a1TestCase.class,
|
||||
ContextHierarchyLevel3a2TestCase.class,
|
||||
ContextHierarchyLevel3bTestCase.class
|
||||
ContextHierarchyLevel3bTestCase.class,
|
||||
TestCase1.class
|
||||
);
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
@@ -158,42 +256,48 @@ class UnusedContextsIntegrationTests {
|
||||
// --- ContextHierarchyLevel1TestCase ------------------------------
|
||||
"ContextRefreshed:ContextHierarchyLevel1TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel1TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase",
|
||||
// No Paused event, since ContextHierarchyLevel2TestCase uses
|
||||
// ContextHierarchyLevel1TestCase as its parent.
|
||||
|
||||
// --- ContextHierarchyLevel2TestCase ------------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel2TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase",
|
||||
// No Paused events, since ContextHierarchyLevel3a1TestCase uses
|
||||
// ContextHierarchyLevel2TestCase and ContextHierarchyLevel1TestCase
|
||||
// as its parents.
|
||||
|
||||
// --- ContextHierarchyLevel3a1TestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel3a1TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase",
|
||||
// No Paused events, since ContextHierarchyLevel3a2TestCase also uses
|
||||
// ContextHierarchyLevel2TestCase and ContextHierarchyLevel1TestCase
|
||||
// as its parents.
|
||||
|
||||
// --- ContextHierarchyLevel3a2TestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel3a1TestCase",
|
||||
"BeforeTestClass:ContextHierarchyLevel3a2TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3a2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase",
|
||||
|
||||
// --- ContextHierarchyLevel3bTestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
// We see a ContextPausedEvent here, since ContextHierarchyLevel3a1TestCase
|
||||
// and ContextHierarchyLevel3a2TestCase are no longer active and we
|
||||
// are "switching" to ContextHierarchyLevel3bTestCase as the active context.
|
||||
// In other words, we pause the inactive context before refreshing the
|
||||
// new, active context.
|
||||
"ContextPaused:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel3bTestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3bTestCase",
|
||||
|
||||
// --- TestCase1 ---------------------------------------------------
|
||||
// Paused, since the previous context hierarchy is no longer used.
|
||||
// Note that the pause order is bottom up.
|
||||
"ContextPaused:ContextHierarchyLevel3bTestCase",
|
||||
"ContextPaused:ContextHierarchyLevel2TestCase",
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase"
|
||||
"ContextPaused:ContextHierarchyLevel1TestCase",
|
||||
// Refreshed, since this is the first time the context is loaded.
|
||||
"ContextRefreshed:TestCase1",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCase1"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -233,7 +337,58 @@ class UnusedContextsIntegrationTests {
|
||||
static class TestCase5 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Config1 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Config2 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Config3 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Config4 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Config5 {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config1.class)
|
||||
static class TestCaseConfig1A extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config1.class)
|
||||
static class TestCaseConfig1B extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config2.class)
|
||||
static class TestCaseConfig2 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config3.class)
|
||||
@DirtiesContext
|
||||
static class TestCaseConfig3 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config4.class)
|
||||
static class TestCaseConfig4 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(Config5.class)
|
||||
static class TestCaseConfig5 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
@TestPropertySource(properties = "magicKey = puzzle")
|
||||
static class EnclosingTestCase {
|
||||
@@ -244,8 +399,8 @@ class UnusedContextsIntegrationTests {
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
|
||||
class NestedTestCase {
|
||||
@Order(1)
|
||||
class NestedTestCase1 {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
@@ -296,6 +451,24 @@ class UnusedContextsIntegrationTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@Order(2)
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
@TestPropertySource(properties = "magicKey = enigma2")
|
||||
class NestedTestCase2 {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("enigma2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
static class TestInstancePerClassEnclosingTestCase extends EnclosingTestCase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user