Skip to content

Commit bd81bb9

Browse files
committed
Polish ModifiedClassPath support
See gh-17491
1 parent 0f0278e commit bd81bb9

File tree

3 files changed

+48
-51
lines changed

3 files changed

+48
-51
lines changed

spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathClassLoaderFactory.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -225,19 +225,16 @@ private ClassPathEntryFilter(MergedAnnotation<ClassPathExclusions> annotation) {
225225
}
226226

227227
private boolean isExcluded(URL url) {
228-
if (!"file".equals(url.getProtocol())) {
229-
return false;
230-
}
231-
String name;
232-
try {
233-
name = new File(url.toURI()).getName();
234-
}
235-
catch (URISyntaxException ex) {
236-
return false;
237-
}
238-
for (String exclusion : this.exclusions) {
239-
if (this.matcher.match(exclusion, name)) {
240-
return true;
228+
if ("file".equals(url.getProtocol())) {
229+
try {
230+
String name = new File(url.toURI()).getName();
231+
for (String exclusion : this.exclusions) {
232+
if (this.matcher.match(exclusion, name)) {
233+
return true;
234+
}
235+
}
236+
}
237+
catch (URISyntaxException ex) {
241238
}
242239
}
243240
return false;

spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/runner/classpath/ModifiedClassPathExtension.java

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,25 @@ public class ModifiedClassPathExtension implements InvocationInterceptor {
5252
@Override
5353
public void interceptBeforeAllMethod(Invocation<Void> invocation,
5454
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
55-
interceptInvocation(invocation, extensionContext);
55+
intercept(invocation, extensionContext);
5656
}
5757

5858
@Override
5959
public void interceptBeforeEachMethod(Invocation<Void> invocation,
6060
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
61-
interceptInvocation(invocation, extensionContext);
61+
intercept(invocation, extensionContext);
6262
}
6363

6464
@Override
6565
public void interceptAfterEachMethod(Invocation<Void> invocation,
6666
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
67-
interceptInvocation(invocation, extensionContext);
67+
intercept(invocation, extensionContext);
6868
}
6969

7070
@Override
7171
public void interceptAfterAllMethod(Invocation<Void> invocation,
7272
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
73-
interceptInvocation(invocation, extensionContext);
73+
intercept(invocation, extensionContext);
7474
}
7575

7676
@Override
@@ -80,62 +80,64 @@ public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocatio
8080
invocation.proceed();
8181
return;
8282
}
83+
fakeInvocation(invocation);
84+
runTestWithModifiedClassPath(invocationContext, extensionContext);
85+
}
86+
87+
private void runTestWithModifiedClassPath(ReflectiveInvocationContext<Method> invocationContext,
88+
ExtensionContext extensionContext) throws ClassNotFoundException, Throwable {
89+
Class<?> testClass = extensionContext.getRequiredTestClass();
90+
Method testMethod = invocationContext.getExecutable();
8391
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
84-
URLClassLoader classLoader = ModifiedClassPathClassLoaderFactory
85-
.createTestClassLoader(extensionContext.getRequiredTestClass());
86-
Thread.currentThread().setContextClassLoader(classLoader);
92+
URLClassLoader modifiedClassLoader = ModifiedClassPathClassLoaderFactory.createTestClassLoader(testClass);
93+
Thread.currentThread().setContextClassLoader(modifiedClassLoader);
8794
try {
88-
fakeInvocation(invocation);
89-
TestExecutionSummary summary = launchTests(invocationContext, extensionContext, classLoader);
90-
if (!CollectionUtils.isEmpty(summary.getFailures())) {
91-
throw summary.getFailures().get(0).getException();
92-
}
93-
}
94-
catch (Exception ex) {
95-
throw ex;
95+
runTest(modifiedClassLoader, testClass.getName(), testMethod.getName());
9696
}
9797
finally {
9898
Thread.currentThread().setContextClassLoader(originalClassLoader);
9999
}
100100
}
101101

102-
private TestExecutionSummary launchTests(ReflectiveInvocationContext<Method> invocationContext,
103-
ExtensionContext extensionContext, URLClassLoader classLoader) throws ClassNotFoundException {
104-
Class<?> testClass = classLoader.loadClass(extensionContext.getRequiredTestClass().getName());
105-
Method method = ReflectionUtils.findMethod(testClass, invocationContext.getExecutable().getName());
102+
private void runTest(URLClassLoader classLoader, String testClassName, String testMethodName)
103+
throws ClassNotFoundException, Throwable {
104+
Class<?> testClass = classLoader.loadClass(testClassName);
105+
Method testMethod = ReflectionUtils.findMethod(testClass, testMethodName);
106106
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
107-
.selectors(DiscoverySelectors.selectMethod(testClass, method)).build();
107+
.selectors(DiscoverySelectors.selectMethod(testClass, testMethod)).build();
108108
Launcher launcher = LauncherFactory.create();
109109
TestPlan testPlan = launcher.discover(request);
110110
SummaryGeneratingListener listener = new SummaryGeneratingListener();
111111
launcher.registerTestExecutionListeners(listener);
112112
launcher.execute(testPlan);
113-
return listener.getSummary();
114-
}
115-
116-
private boolean isModifiedClassPathClassLoader(ExtensionContext extensionContext) {
117-
return extensionContext.getRequiredTestClass().getClassLoader().getClass().getName()
118-
.equals(ModifiedClassPathClassLoader.class.getName());
113+
TestExecutionSummary summary = listener.getSummary();
114+
if (!CollectionUtils.isEmpty(summary.getFailures())) {
115+
throw summary.getFailures().get(0).getException();
116+
}
119117
}
120118

121-
private void interceptInvocation(Invocation<Void> invocation, ExtensionContext extensionContext) throws Throwable {
119+
private void intercept(Invocation<Void> invocation, ExtensionContext extensionContext) throws Throwable {
122120
if (isModifiedClassPathClassLoader(extensionContext)) {
123121
invocation.proceed();
122+
return;
124123
}
125-
else {
126-
fakeInvocation(invocation);
127-
}
124+
fakeInvocation(invocation);
128125
}
129126

130-
private void fakeInvocation(Invocation invocation) {
127+
private void fakeInvocation(Invocation<Void> invocation) {
131128
try {
132129
Field field = ReflectionUtils.findField(invocation.getClass(), "invoked");
133130
ReflectionUtils.makeAccessible(field);
134131
ReflectionUtils.setField(field, invocation, new AtomicBoolean(true));
135132
}
136-
catch (Throwable ignore) {
137-
133+
catch (Throwable ex) {
138134
}
139135
}
140136

137+
private boolean isModifiedClassPathClassLoader(ExtensionContext extensionContext) {
138+
Class<?> testClass = extensionContext.getRequiredTestClass();
139+
ClassLoader classLoader = testClass.getClassLoader();
140+
return classLoader.getClass().getName().equals(ModifiedClassPathClassLoader.class.getName());
141+
}
142+
141143
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.io.File;
2020
import java.io.IOException;
21-
import java.nio.file.Files;
2221
import java.nio.file.Path;
2322
import java.util.Collections;
2423
import java.util.HashMap;
@@ -38,6 +37,7 @@
3837
import org.junit.jupiter.api.BeforeEach;
3938
import org.junit.jupiter.api.Test;
4039
import org.junit.jupiter.api.extension.ExtendWith;
40+
import org.junit.jupiter.api.io.TempDir;
4141
import org.slf4j.bridge.SLF4JBridgeHandler;
4242
import org.slf4j.impl.StaticLoggerBinder;
4343

@@ -69,7 +69,6 @@
6969
import org.springframework.core.env.MapPropertySource;
7070
import org.springframework.core.env.MutablePropertySources;
7171
import org.springframework.test.util.ReflectionTestUtils;
72-
import org.springframework.util.FileSystemUtils;
7372

7473
import static org.assertj.core.api.Assertions.assertThat;
7574
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -102,7 +101,8 @@ class LoggingApplicationListenerTests {
102101

103102
private final GenericApplicationContext context = new GenericApplicationContext();
104103

105-
private Path tempDir;
104+
@TempDir
105+
public Path tempDir;
106106

107107
private File logFile;
108108

@@ -111,7 +111,6 @@ class LoggingApplicationListenerTests {
111111
@BeforeEach
112112
void init(CapturedOutput output) throws SecurityException, IOException {
113113
this.output = output;
114-
this.tempDir = Files.createTempDirectory("logging-application-listener-tests");
115114
this.logFile = new File(this.tempDir.toFile(), "foo.log");
116115
LogManager.getLogManager().readConfiguration(JavaLoggingSystem.class.getResourceAsStream("logging.properties"));
117116
multicastEvent(new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
@@ -128,7 +127,6 @@ void clear() throws IOException {
128127
if (loggingSystem.getShutdownHandler() != null) {
129128
loggingSystem.getShutdownHandler().run();
130129
}
131-
FileSystemUtils.deleteRecursively(this.tempDir);
132130
System.clearProperty(LoggingSystem.class.getName());
133131
System.clearProperty(LoggingSystemProperties.LOG_FILE);
134132
System.clearProperty(LoggingSystemProperties.LOG_PATH);

0 commit comments

Comments
 (0)