mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-24 15:49:26 +00:00
Pause unused application contexts in the TestContext framework
Since the introduction of the Spring TestContext Framework in 2007, application contexts have always been stored in the context cache in a "running" state. However, leaving a context running means that components in the context may continue to run in the background. For example, JMS listeners may continue to consume messages from a queue; scheduled tasks may continue to perform active work, etc.; and this can lead to issues within a test suite. To address such issues, this commit introduces built-in support for pausing application contexts when they are not in use and restarting them if they are needed again. Specifically, the TestContextManager now marks a test's application context as "unused" after execution of the test class has ended, and the underlying ContextCache then "stops" the application context if no other test class is currently using the context. When a TestExecutionListener later attempts to obtain a paused application context -- for example, for a subsequent test class that shares the same application context -- the ContextCache ensures that context is restarted before returning it. See https://github.com/spring-projects/spring-boot/issues/28312 See gh-35171 Closes gh-35168
This commit is contained in:
+16
-16
@@ -64,7 +64,7 @@ class ClassLevelDirtiesContextTestNGTests {
|
||||
// for example, via JUnit's @Suite.
|
||||
cacheHits.set(0);
|
||||
cacheMisses.set(0);
|
||||
assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("BeforeClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,63 +74,63 @@ class ClassLevelDirtiesContextTestNGTests {
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and default class mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_CLASS mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3);
|
||||
assertContextCacheStatistics(
|
||||
"after class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(),
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, 0, cacheHits.get(),
|
||||
cacheMisses.incrementAndGet());
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(),
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, 0, cacheHits.get(),
|
||||
cacheMisses.incrementAndGet());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
}
|
||||
|
||||
private void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) {
|
||||
@@ -152,12 +152,12 @@ class ClassLevelDirtiesContextTestNGTests {
|
||||
|
||||
private void assertBehaviorForCleanTestCase() {
|
||||
runTestClassAndAssertStats(CleanTestCase.class, 1);
|
||||
assertContextCacheStatistics("after clean test class", 1, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
assertContextCacheStatistics("after clean test class", 1, 0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void verifyFinalCacheState() {
|
||||
assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("AfterClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+19
-19
@@ -62,81 +62,81 @@ class ClassLevelDirtiesContextTests {
|
||||
// for example, via JUnit's @Suite.
|
||||
cacheHits.set(0);
|
||||
cacheMisses.set(0);
|
||||
assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("BeforeClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyDirtiesContextBehavior() throws Exception {
|
||||
void verifyDirtiesContextBehavior() {
|
||||
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and default class mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_CLASS mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3);
|
||||
assertContextCacheStatistics(
|
||||
"after class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithAfterEachTestMethodModeTestCase.class, 3);
|
||||
assertContextCacheStatistics(
|
||||
"after inherited class-level @DirtiesContext with clean test method and AFTER_EACH_TEST_METHOD mode", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.addAndGet(2));
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(),
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, 0, cacheHits.get(),
|
||||
cacheMisses.incrementAndGet());
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, cacheHits.get(),
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with dirty test method", 0, 0, cacheHits.get(),
|
||||
cacheMisses.incrementAndGet());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
runTestClassAndAssertStats(InheritedClassLevelDirtiesContextWithDirtyMethodsTestCase.class, 1);
|
||||
assertContextCacheStatistics("after inherited class-level @DirtiesContext with dirty test method", 0,
|
||||
cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
assertBehaviorForCleanTestCase();
|
||||
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndAfterClassModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and AFTER_CLASS mode",
|
||||
0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
0, 0, cacheHits.incrementAndGet(), cacheMisses.get());
|
||||
}
|
||||
|
||||
private void assertBehaviorForCleanTestCase() throws Exception {
|
||||
private void assertBehaviorForCleanTestCase() {
|
||||
runTestClassAndAssertStats(CleanTestCase.class, 1);
|
||||
assertContextCacheStatistics("after clean test class", 1, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
assertContextCacheStatistics("after clean test class", 1, 0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
}
|
||||
|
||||
private void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) throws Exception {
|
||||
private void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) {
|
||||
EngineTestKit.engine("junit-jupiter")
|
||||
.selectors(selectClass(testClass))
|
||||
.execute()
|
||||
@@ -151,7 +151,7 @@ class ClassLevelDirtiesContextTests {
|
||||
|
||||
@AfterAll
|
||||
static void verifyFinalCacheState() {
|
||||
assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("AfterClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+28
-8
@@ -44,7 +44,17 @@ public class ContextCacheTestUtils {
|
||||
* @param expectedMissCount the expected miss count
|
||||
*/
|
||||
public static void assertContextCacheStatistics(int expectedSize, int expectedHitCount, int expectedMissCount) {
|
||||
assertContextCacheStatistics(null, expectedSize, expectedHitCount, expectedMissCount);
|
||||
ContextCache contextCache = DefaultCacheAwareContextLoaderDelegate.defaultContextCache;
|
||||
String context = (StringUtils.hasText((String) null) ? " (" + null + ")" : "");
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(contextCache.size())
|
||||
.as("contexts in cache" + context).isEqualTo(expectedSize);
|
||||
softly.assertThat(contextCache.getHitCount())
|
||||
.as("cache hits" + context).isEqualTo(expectedHitCount);
|
||||
softly.assertThat(contextCache.getMissCount())
|
||||
.as("cache misses" + context).isEqualTo(expectedMissCount);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,13 +62,16 @@ public class ContextCacheTestUtils {
|
||||
*
|
||||
* @param usageScenario the scenario in which the statistics are used
|
||||
* @param expectedSize the expected number of contexts in the cache
|
||||
* @param expectedContextUsageCount the expected number of actively running
|
||||
* contexts in the cache
|
||||
* @param expectedHitCount the expected hit count
|
||||
* @param expectedMissCount the expected miss count
|
||||
*/
|
||||
public static void assertContextCacheStatistics(String usageScenario, int expectedSize, int expectedHitCount,
|
||||
int expectedMissCount) {
|
||||
public static void assertContextCacheStatistics(String usageScenario, int expectedSize,
|
||||
int expectedContextUsageCount, int expectedHitCount, int expectedMissCount) {
|
||||
|
||||
assertContextCacheStatistics(DefaultCacheAwareContextLoaderDelegate.defaultContextCache, usageScenario,
|
||||
expectedSize, expectedHitCount, expectedMissCount);
|
||||
expectedSize, expectedContextUsageCount, expectedHitCount, expectedMissCount);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,18 +80,25 @@ public class ContextCacheTestUtils {
|
||||
* @param contextCache the cache to assert against
|
||||
* @param usageScenario the scenario in which the statistics are used
|
||||
* @param expectedSize the expected number of contexts in the cache
|
||||
* @param expectedContextUsageCount the expected number of actively running
|
||||
* contexts in the cache
|
||||
* @param expectedHitCount the expected hit count
|
||||
* @param expectedMissCount the expected miss count
|
||||
*/
|
||||
public static void assertContextCacheStatistics(ContextCache contextCache, String usageScenario,
|
||||
int expectedSize, int expectedHitCount, int expectedMissCount) {
|
||||
int expectedSize, int expectedContextUsageCount, int expectedHitCount, int expectedMissCount) {
|
||||
|
||||
String context = (StringUtils.hasText(usageScenario) ? " (" + usageScenario + ")" : "");
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(contextCache.size()).as("contexts in cache" + context).isEqualTo(expectedSize);
|
||||
softly.assertThat(contextCache.getHitCount()).as("cache hits" + context).isEqualTo(expectedHitCount);
|
||||
softly.assertThat(contextCache.getMissCount()).as("cache misses" + context).isEqualTo(expectedMissCount);
|
||||
softly.assertThat(contextCache.size())
|
||||
.as("contexts in cache" + context).isEqualTo(expectedSize);
|
||||
softly.assertThat(contextCache.getContextUsageCount())
|
||||
.as("active contexts in cache" + context).isEqualTo(expectedContextUsageCount);
|
||||
softly.assertThat(contextCache.getHitCount())
|
||||
.as("cache hits" + context).isEqualTo(expectedHitCount);
|
||||
softly.assertThat(contextCache.getMissCount())
|
||||
.as("cache misses" + context).isEqualTo(expectedMissCount);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+87
-103
@@ -19,13 +19,11 @@ package org.springframework.test.context.cache;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.ActiveProfilesResolver;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestContextTestUtils;
|
||||
@@ -52,7 +50,7 @@ class ContextCacheTests {
|
||||
|
||||
@BeforeEach
|
||||
void initialCacheState() {
|
||||
assertContextCacheStatistics(contextCache, "initial state", 0, 0, 0);
|
||||
assertContextCacheStatistics(contextCache, "initial state", 0, 0, 0, 0);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -64,38 +62,39 @@ class ContextCacheTests {
|
||||
return (MergedContextConfiguration) ReflectionTestUtils.getField(testContext, "mergedConfig");
|
||||
}
|
||||
|
||||
private ApplicationContext loadContext(Class<?> testClass) {
|
||||
private void loadCtxAndAssertStats(Class<?> testClass, int expectedSize, int expectedActiveContextsCount,
|
||||
int expectedHitCount, int expectedMissCount) {
|
||||
|
||||
TestContext testContext = TestContextTestUtils.buildTestContext(testClass, contextCache);
|
||||
return testContext.getApplicationContext();
|
||||
|
||||
assertThat(testContext.getApplicationContext()).isNotNull();
|
||||
assertContextCacheStatistics(contextCache, testClass.getName(), expectedSize, expectedActiveContextsCount,
|
||||
expectedHitCount, expectedMissCount);
|
||||
testContext.markApplicationContextUnused();
|
||||
}
|
||||
|
||||
private void loadCtxAndAssertStats(Class<?> testClass, int expectedSize, int expectedHitCount, int expectedMissCount) {
|
||||
assertThat(loadContext(testClass)).isNotNull();
|
||||
assertContextCacheStatistics(contextCache, testClass.getName(), expectedSize, expectedHitCount,
|
||||
expectedMissCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyCacheKeyIsBasedOnContextLoader() {
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 1, 0, 1);
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 1, 1, 1);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 1, 2);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 2, 2);
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 2, 3, 2);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 4, 2);
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 1, 1, 0, 1);
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 1, 1, 1, 1);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 1, 1, 2);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 1, 2, 2);
|
||||
loadCtxAndAssertStats(AnnotationConfigContextLoaderTestCase.class, 2, 1, 3, 2);
|
||||
loadCtxAndAssertStats(CustomAnnotationConfigContextLoaderTestCase.class, 2, 1, 4, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyCacheKeyIsBasedOnActiveProfiles() {
|
||||
int size = 0, hit = 0, miss = 0;
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, ++size, hit, ++miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, ++size, 1, hit, ++miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, 1, ++hit, miss);
|
||||
// Profiles {foo, bar} should not hash to the same as {bar,foo}
|
||||
loadCtxAndAssertStats(BarFooProfilesTestCase.class, ++size, hit, ++miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
|
||||
loadCtxAndAssertStats(BarFooProfilesTestCase.class, size, ++hit, miss);
|
||||
loadCtxAndAssertStats(FooBarActiveProfilesResolverTestCase.class, size, ++hit, miss);
|
||||
loadCtxAndAssertStats(BarFooProfilesTestCase.class, ++size, 1, hit, ++miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, 1, ++hit, miss);
|
||||
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, 1, ++hit, miss);
|
||||
loadCtxAndAssertStats(BarFooProfilesTestCase.class, size, 1, ++hit, miss);
|
||||
loadCtxAndAssertStats(FooBarActiveProfilesResolverTestCase.class, size, 1, ++hit, miss);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,24 +104,24 @@ class ContextCacheTests {
|
||||
int misses = 0;
|
||||
|
||||
// Level 1
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel1TestCase.class, ++size, hits, ++misses);
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel1TestCase.class, size, ++hits, misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel1TestCase.class, ++size, 1, hits, ++misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel1TestCase.class, size, 1, ++hits, misses);
|
||||
|
||||
// Level 2
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel2TestCase.class, ++size /* L2 */, ++hits /* L1 */,
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel2TestCase.class, ++size /* L2 */, 2, ++hits /* L1 */,
|
||||
++misses /* L2 */);
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel2TestCase.class, size, ++hits /* L2 */, misses);
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel2TestCase.class, size, ++hits /* L2 */, misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel2TestCase.class, size, 2, ++hits /* L2 */, misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel2TestCase.class, size, 2, ++hits /* L2 */, misses);
|
||||
|
||||
// Level 3-A
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel3aTestCase.class, ++size /* L3A */, ++hits /* L2 */,
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel3a1TestCase.class, ++size /* L3A */, 3, ++hits /* L2 */,
|
||||
++misses /* L3A */);
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel3aTestCase.class, size, ++hits /* L3A */, misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel3a1TestCase.class, size, 3, ++hits /* L3A */, misses);
|
||||
|
||||
// Level 3-B
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel3bTestCase.class, ++size /* L3B */, ++hits /* L2 */,
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel3bTestCase.class, ++size /* L3B */, 3, ++hits /* L2 */,
|
||||
++misses /* L3B */);
|
||||
loadCtxAndAssertStats(ClassHierarchyContextHierarchyLevel3bTestCase.class, size, ++hits /* L3B */, misses);
|
||||
loadCtxAndAssertStats(ContextHierarchyLevel3bTestCase.class, size, 3, ++hits /* L3B */, misses);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -130,23 +129,27 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 1
|
||||
// Should also remove Levels 2, 3-A, and 3-B, leaving nothing.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a).getParent().getParent(),
|
||||
HierarchyMode.CURRENT_LEVEL);
|
||||
assertContextCacheStatistics(contextCache, "removed level 1", 0, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 1", 0, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -155,23 +158,27 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 1
|
||||
// Should also remove Levels 2, 3-A, and 3-B, leaving nothing.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a).getParent().getParent(),
|
||||
HierarchyMode.EXHAUSTIVE);
|
||||
assertContextCacheStatistics(contextCache, "removed level 1", 0, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 1", 0, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -180,24 +187,28 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 2
|
||||
// Should also remove Levels 3-A and 3-B, leaving only Level 1 as a context in the
|
||||
// cache but also removing the Level 1 hierarchy since all children have been
|
||||
// removed.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a).getParent(), HierarchyMode.CURRENT_LEVEL);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 1, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 1, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -206,22 +217,26 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 2
|
||||
// Should wipe the cache
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a).getParent(), HierarchyMode.EXHAUSTIVE);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 0, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 0, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -230,27 +245,31 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 3-A
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a), HierarchyMode.CURRENT_LEVEL);
|
||||
assertContextCacheStatistics(contextCache, "removed level 3-A", 3, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 3-A", 3, 0, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
|
||||
// Remove Level 2
|
||||
// Should also remove Level 3-B, leaving only Level 1.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3b).getParent(), HierarchyMode.CURRENT_LEVEL);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 1, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 1, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -259,29 +278,33 @@ class ContextCacheTests {
|
||||
|
||||
// Load Level 3-A
|
||||
TestContext testContext3a = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3aTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3a1TestCase.class, contextCache);
|
||||
testContext3a.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 3);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 3, 0, 3);
|
||||
assertParentContextCount(2);
|
||||
testContext3a.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A", 3, 0, 0, 3);
|
||||
|
||||
// Load Level 3-B
|
||||
TestContext testContext3b = TestContextTestUtils.buildTestContext(
|
||||
ClassHierarchyContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
ContextHierarchyLevel3bTestCase.class, contextCache);
|
||||
testContext3b.getApplicationContext();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 3, 1, 4);
|
||||
assertParentContextCount(2);
|
||||
testContext3b.markApplicationContextUnused();
|
||||
assertContextCacheStatistics(contextCache, "level 3, A and B", 4, 0, 1, 4);
|
||||
|
||||
// Remove Level 3-A
|
||||
// Should wipe the cache.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3a), HierarchyMode.EXHAUSTIVE);
|
||||
assertContextCacheStatistics(contextCache, "removed level 3-A", 0, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 3-A", 0, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
|
||||
// Remove Level 2
|
||||
// Should not actually do anything since the cache was cleared in the
|
||||
// previous step. So the stats should remain the same.
|
||||
contextCache.remove(getMergedContextConfiguration(testContext3b).getParent(), HierarchyMode.EXHAUSTIVE);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 0, 1, 4);
|
||||
assertContextCacheStatistics(contextCache, "removed level 2", 0, 0, 1, 4);
|
||||
assertParentContextCount(0);
|
||||
}
|
||||
|
||||
@@ -324,43 +347,4 @@ class ContextCacheTests {
|
||||
private static class FooBarActiveProfilesResolverTestCase {
|
||||
}
|
||||
|
||||
@ContextHierarchy({ @ContextConfiguration })
|
||||
private static class ClassHierarchyContextHierarchyLevel1TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level1Config {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ContextHierarchy({ @ContextConfiguration })
|
||||
private static class ClassHierarchyContextHierarchyLevel2TestCase extends
|
||||
ClassHierarchyContextHierarchyLevel1TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level2Config {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ContextHierarchy({ @ContextConfiguration })
|
||||
private static class ClassHierarchyContextHierarchyLevel3aTestCase extends
|
||||
ClassHierarchyContextHierarchyLevel2TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level3aConfig {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ContextHierarchy({ @ContextConfiguration })
|
||||
private static class ClassHierarchyContextHierarchyLevel3bTestCase extends
|
||||
ClassHierarchyContextHierarchyLevel2TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level3bConfig {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
spring-test/src/test/java/org/springframework/test/context/cache/ContextHierarchyLevel1TestCase.java
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ContextCustomizerFactories;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
class ContextHierarchyLevel1TestCase {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(EventTracker.class)
|
||||
static class Level1Config {
|
||||
}
|
||||
|
||||
}
|
||||
spring-test/src/test/java/org/springframework/test/context/cache/ContextHierarchyLevel2TestCase.java
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@ContextHierarchy(@ContextConfiguration)
|
||||
class ContextHierarchyLevel2TestCase extends ContextHierarchyLevel1TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level2Config {
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@ContextHierarchy(@ContextConfiguration)
|
||||
class ContextHierarchyLevel3a1TestCase extends ContextHierarchyLevel2TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level3a1Config {
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@ContextHierarchy(@ContextConfiguration(classes = ContextHierarchyLevel3a1TestCase.Level3a1Config.class))
|
||||
class ContextHierarchyLevel3a2TestCase extends ContextHierarchyLevel2TestCase {
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@ContextHierarchy(@ContextConfiguration)
|
||||
class ContextHierarchyLevel3bTestCase extends ContextHierarchyLevel2TestCase {
|
||||
|
||||
@Configuration
|
||||
static class Level3bConfig {
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.ContextCustomizerFactory;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
class DisplayNameCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
@Override
|
||||
public @Nullable ContextCustomizer createContextCustomizer(Class<?> testClass,
|
||||
List<ContextConfigurationAttributes> __) {
|
||||
|
||||
return (context, mergedConfig) ->
|
||||
((AbstractApplicationContext) context).setDisplayName(mergedConfig.getTestClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.ApplicationContextEvent;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.event.ContextRestartedEvent;
|
||||
import org.springframework.context.event.ContextStoppedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.test.context.event.TestContextEvent;
|
||||
import org.springframework.test.context.event.annotation.AfterTestClass;
|
||||
import org.springframework.test.context.event.annotation.BeforeTestClass;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
@Component
|
||||
class EventTracker {
|
||||
|
||||
static final List<String> events = new ArrayList<>();
|
||||
|
||||
|
||||
@EventListener(ContextRefreshedEvent.class)
|
||||
void contextRefreshed(ContextRefreshedEvent event) {
|
||||
trackApplicationContextEvent(event);
|
||||
}
|
||||
|
||||
@EventListener(ContextRestartedEvent.class)
|
||||
void contextRestarted(ContextRestartedEvent event) {
|
||||
trackApplicationContextEvent(event);
|
||||
}
|
||||
|
||||
@EventListener(ContextStoppedEvent.class)
|
||||
void contextStopped(ContextStoppedEvent event) {
|
||||
trackApplicationContextEvent(event);
|
||||
}
|
||||
|
||||
@EventListener(ContextClosedEvent.class)
|
||||
void contextClosed(ContextClosedEvent event) {
|
||||
trackApplicationContextEvent(event);
|
||||
}
|
||||
|
||||
@BeforeTestClass
|
||||
void beforeTestClass(TestContextEvent event) {
|
||||
trackTestContextEvent(event);
|
||||
}
|
||||
|
||||
@AfterTestClass
|
||||
void afterTestClass(TestContextEvent event) {
|
||||
trackTestContextEvent(event);
|
||||
}
|
||||
|
||||
private static void trackApplicationContextEvent(ApplicationContextEvent event) {
|
||||
events.add(eventName(event) + ":" + event.getSource().getDisplayName());
|
||||
}
|
||||
|
||||
private static void trackTestContextEvent(TestContextEvent event) {
|
||||
events.add(eventName(event) + ":" +
|
||||
event.getSource().getTestClass().getSimpleName());
|
||||
}
|
||||
|
||||
private static String eventName(ApplicationEvent event) {
|
||||
String name = event.getClass().getSimpleName();
|
||||
return name.substring(0, name.length() - "Event".length());
|
||||
}
|
||||
|
||||
}
|
||||
+5
-5
@@ -61,19 +61,19 @@ class SpringExtensionContextCacheTests {
|
||||
static void verifyInitialCacheState() {
|
||||
dirtiedApplicationContext = null;
|
||||
resetContextCache();
|
||||
assertContextCacheStatistics("BeforeClass", 0, 0, 0);
|
||||
assertContextCacheStatistics("BeforeClass", 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void verifyFinalCacheState() {
|
||||
assertContextCacheStatistics("AfterClass", 1, 1, 2);
|
||||
assertContextCacheStatistics("AfterClass", 1, 1, 1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
@Order(1)
|
||||
void dirtyContext() {
|
||||
assertContextCacheStatistics("dirtyContext()", 1, 0, 1);
|
||||
assertContextCacheStatistics("dirtyContext()", 1, 1, 0, 1);
|
||||
assertThat(this.applicationContext).as("The application context should have been autowired.").isNotNull();
|
||||
SpringExtensionContextCacheTests.dirtiedApplicationContext = this.applicationContext;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class SpringExtensionContextCacheTests {
|
||||
@Test
|
||||
@Order(2)
|
||||
void verifyContextDirty() {
|
||||
assertContextCacheStatistics("verifyContextWasDirtied()", 1, 0, 2);
|
||||
assertContextCacheStatistics("verifyContextWasDirtied()", 1, 1, 0, 2);
|
||||
assertThat(this.applicationContext).as("The application context should have been autowired.").isNotNull();
|
||||
assertThat(this.applicationContext).as("The application context should have been 'dirtied'.").isNotSameAs(SpringExtensionContextCacheTests.dirtiedApplicationContext);
|
||||
SpringExtensionContextCacheTests.dirtiedApplicationContext = this.applicationContext;
|
||||
@@ -90,7 +90,7 @@ class SpringExtensionContextCacheTests {
|
||||
@Test
|
||||
@Order(3)
|
||||
void verifyContextNotDirty() {
|
||||
assertContextCacheStatistics("verifyContextWasNotDirtied()", 1, 1, 2);
|
||||
assertContextCacheStatistics("verifyContextWasNotDirtied()", 1, 1, 1, 2);
|
||||
assertThat(this.applicationContext).as("The application context should have been autowired.").isNotNull();
|
||||
assertThat(this.applicationContext).as("The application context should NOT have been 'dirtied'.").isSameAs(SpringExtensionContextCacheTests.dirtiedApplicationContext);
|
||||
}
|
||||
|
||||
spring-test/src/test/java/org/springframework/test/context/cache/UnusedContextsIntegrationTests.java
Vendored
+308
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2002-present 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.cache;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.ClassOrderer;
|
||||
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.platform.engine.discovery.ClassSelector;
|
||||
import org.junit.platform.engine.discovery.DiscoverySelectors;
|
||||
import org.junit.platform.testkit.engine.EngineTestKit;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
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.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
|
||||
|
||||
/**
|
||||
* Integration tests for pausing and restarting "unused" contexts.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
* @see TestContext#markApplicationContextUnused()
|
||||
*/
|
||||
class UnusedContextsIntegrationTests {
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void clearApplicationEvents() {
|
||||
EventTracker.events.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void topLevelTestClassesWithSharedApplicationContext() {
|
||||
runTestClasses(5, TestCase1.class, TestCase2.class, TestCase3.class, TestCase4.class, TestCase5.class);
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
|
||||
// --- TestCase1 -----------------------------------------------
|
||||
// Refreshed instead of Restarted, 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",
|
||||
"ContextStopped:TestCase1",
|
||||
|
||||
// --- TestCase2 -----------------------------------------------
|
||||
"ContextRestarted:TestCase1",
|
||||
"BeforeTestClass:TestCase2",
|
||||
"AfterTestClass:TestCase2",
|
||||
"ContextStopped:TestCase1",
|
||||
|
||||
// --- TestCase3 -----------------------------------------------
|
||||
"ContextRestarted:TestCase1",
|
||||
"BeforeTestClass:TestCase3",
|
||||
"AfterTestClass:TestCase3",
|
||||
// Closed instead of Stopped, since TestCase3 uses @DirtiesContext
|
||||
"ContextClosed:TestCase1",
|
||||
|
||||
// --- TestCase4 -----------------------------------------------
|
||||
// Refreshed instead of Restarted, since TestCase3 uses @DirtiesContext
|
||||
"ContextRefreshed:TestCase4",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
"AfterTestClass:TestCase4",
|
||||
"ContextStopped:TestCase4",
|
||||
|
||||
// --- TestCase5 -----------------------------------------------
|
||||
"ContextRestarted:TestCase4",
|
||||
"BeforeTestClass:TestCase5",
|
||||
"AfterTestClass:TestCase5",
|
||||
"ContextStopped:TestCase4"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassesInNestedTestHierarchy() {
|
||||
runTestClasses(5, EnclosingTestCase.class);
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
|
||||
// --- EnclosingTestCase -------------------------------------------
|
||||
"ContextRefreshed:EnclosingTestCase",
|
||||
// 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
|
||||
// active context used by EnclosingTestCase.
|
||||
"BeforeTestClass:NestedTestCase",
|
||||
|
||||
// --- OverridingNestedTestCase1 ---------------------------
|
||||
"ContextRefreshed:OverridingNestedTestCase1",
|
||||
// No BeforeTestClass, since EventPublishingTestExecutionListener
|
||||
// only publishes events for a context that has already been loaded.
|
||||
|
||||
// --- InheritingNestedTestCase ------------------------
|
||||
// No Refreshed or Restarted event, since InheritingNestedTestCase
|
||||
// shares the active context used by OverridingNestedTestCase1.
|
||||
"BeforeTestClass:InheritingNestedTestCase",
|
||||
"AfterTestClass:InheritingNestedTestCase",
|
||||
// No Stopped event, since OverridingNestedTestCase1 is still
|
||||
// using the context
|
||||
|
||||
"AfterTestClass:OverridingNestedTestCase1",
|
||||
"ContextStopped:OverridingNestedTestCase1",
|
||||
|
||||
// --- OverridingNestedTestCase2 ---------------------------
|
||||
"ContextRestarted:OverridingNestedTestCase1",
|
||||
"BeforeTestClass:OverridingNestedTestCase2",
|
||||
"AfterTestClass:OverridingNestedTestCase2",
|
||||
"ContextStopped:OverridingNestedTestCase1",
|
||||
|
||||
"AfterTestClass:NestedTestCase",
|
||||
// No Stopped event, since EnclosingTestCase is still using the context
|
||||
|
||||
"AfterTestClass:EnclosingTestCase",
|
||||
"ContextStopped:EnclosingTestCase"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassesWithContextHierarchies() {
|
||||
runTestClasses(5,
|
||||
ContextHierarchyLevel1TestCase.class,
|
||||
ContextHierarchyLevel2TestCase.class,
|
||||
ContextHierarchyLevel3a1TestCase.class,
|
||||
ContextHierarchyLevel3a2TestCase.class,
|
||||
ContextHierarchyLevel3bTestCase.class
|
||||
);
|
||||
|
||||
assertThat(EventTracker.events).containsExactly(
|
||||
|
||||
// --- ContextHierarchyLevel1TestCase ------------------------------
|
||||
"ContextRefreshed:ContextHierarchyLevel1TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel1TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel1TestCase",
|
||||
|
||||
// --- ContextHierarchyLevel2TestCase ------------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel2TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel1TestCase",
|
||||
|
||||
// --- ContextHierarchyLevel3a1TestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel3a1TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel1TestCase",
|
||||
|
||||
// --- ContextHierarchyLevel3a2TestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel3a1TestCase",
|
||||
"BeforeTestClass:ContextHierarchyLevel3a2TestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3a2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel3a1TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel1TestCase",
|
||||
|
||||
// --- ContextHierarchyLevel3bTestCase -----------------------------
|
||||
"ContextRestarted:ContextHierarchyLevel1TestCase",
|
||||
"ContextRestarted:ContextHierarchyLevel2TestCase",
|
||||
"ContextRefreshed:ContextHierarchyLevel3bTestCase",
|
||||
"AfterTestClass:ContextHierarchyLevel3bTestCase",
|
||||
"ContextStopped:ContextHierarchyLevel3bTestCase",
|
||||
"ContextStopped:ContextHierarchyLevel2TestCase",
|
||||
"ContextStopped:ContextHierarchyLevel1TestCase"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static void runTestClasses(int expectedTestCount, Class<?>... classes) {
|
||||
EngineTestKit.engine("junit-jupiter")
|
||||
.selectors(selectClasses(classes))
|
||||
.execute()
|
||||
.testEvents()
|
||||
.assertStatistics(stats -> stats.started(expectedTestCount).succeeded(expectedTestCount));
|
||||
}
|
||||
|
||||
private static ClassSelector[] selectClasses(Class<?>... classes) {
|
||||
return Arrays.stream(classes).map(DiscoverySelectors::selectClass).toArray(ClassSelector[]::new);
|
||||
}
|
||||
|
||||
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
private abstract static class AbstractTestCase {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
static class TestCase1 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
static class TestCase2 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@DirtiesContext
|
||||
static class TestCase3 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
static class TestCase4 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
static class TestCase5 extends AbstractTestCase {
|
||||
}
|
||||
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
@TestPropertySource(properties = "magicKey = puzzle")
|
||||
static class EnclosingTestCase {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("puzzle");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
|
||||
class NestedTestCase {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("puzzle");
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates configuration of {@link OverridingNestedTestCase2}.
|
||||
*/
|
||||
@Nested
|
||||
@Order(1)
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
@TestPropertySource(properties = "magicKey = enigma")
|
||||
class OverridingNestedTestCase1 {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritingNestedTestCase {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("enigma");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates configuration of {@link OverridingNestedTestCase1}.
|
||||
*/
|
||||
@Nested
|
||||
@Order(2)
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(EventTracker.class)
|
||||
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class)
|
||||
@TestPropertySource(properties = "magicKey = enigma")
|
||||
class OverridingNestedTestCase2 {
|
||||
|
||||
@Test
|
||||
void test(@Value("${magicKey}") String magicKey) {
|
||||
assertThat(magicKey).isEqualTo("enigma");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -55,19 +55,19 @@ class DirtiesContextInterfaceTests {
|
||||
// for example, via JUnit's @Suite.
|
||||
cacheHits.set(0);
|
||||
cacheMisses.set(0);
|
||||
assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("BeforeClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void verifyFinalCacheState() {
|
||||
assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get());
|
||||
assertContextCacheStatistics("AfterClass", 0, 0, cacheHits.get(), cacheMisses.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyDirtiesContextBehavior() throws Exception {
|
||||
runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1);
|
||||
assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode",
|
||||
0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
0, 0, cacheHits.get(), cacheMisses.incrementAndGet());
|
||||
}
|
||||
|
||||
private void runTestClassAndAssertStats(Class<?> testClass, int expectedTestCount) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user