Skip to content

Commit 2c39b96

Browse files
committed
Add ClasspathRunner test utility
1 parent 111fc97 commit 2c39b96

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.jupiter.api;
12+
13+
import java.io.IOException;
14+
import java.io.UncheckedIOException;
15+
import java.net.URL;
16+
import java.net.URLClassLoader;
17+
18+
/**
19+
* Utility class for running code with a custom classpath.
20+
*
21+
* @since 5.13
22+
*/
23+
public class ClasspathRunner {
24+
25+
private ClasspathRunner() {
26+
}
27+
28+
/**
29+
* Execute the {@link Runnable} within a custom classpath, temporarily modifying the
30+
* thread's context class loader to include the provided {@code classpathRoot}.
31+
*
32+
* <p>After the given {@code Runnable} completes, the original context class loader is
33+
* restored.
34+
*
35+
* @param classpathRoot the root path to be added to the classpath, resolved relative
36+
* to the current thread's {@link Thread#getContextClassLoader() context class loader}.
37+
* @param runnable the {@code Runnable} to execute with the temporary classpath.
38+
*/
39+
public static void withClasspath(String classpathRoot, Runnable runnable) {
40+
var current = Thread.currentThread().getContextClassLoader();
41+
try (var classLoader = new URLClassLoader(new URL[] { current.getResource(classpathRoot) }, current)) {
42+
Thread.currentThread().setContextClassLoader(classLoader);
43+
runnable.run();
44+
}
45+
catch (IOException e) {
46+
throw new UncheckedIOException(e);
47+
}
48+
finally {
49+
Thread.currentThread().setContextClassLoader(current);
50+
}
51+
}
52+
53+
}

platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@
1919
import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS;
2020
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
2121

22-
import java.io.IOException;
23-
import java.io.UncheckedIOException;
24-
import java.net.URL;
25-
import java.net.URLClassLoader;
2622
import java.util.concurrent.atomic.AtomicReference;
2723
import java.util.logging.LogRecord;
2824

25+
import org.junit.jupiter.api.ClasspathRunner;
2926
import org.junit.jupiter.api.Tag;
3027
import org.junit.jupiter.api.Test;
3128
import org.junit.jupiter.api.extension.BeforeAllCallback;
@@ -434,18 +431,7 @@ private static void withSystemProperty(String key, String value, Runnable runnab
434431
}
435432

436433
private static void withTestServices(Runnable runnable) {
437-
var current = Thread.currentThread().getContextClassLoader();
438-
var url = LauncherFactoryTests.class.getClassLoader().getResource("testservices/");
439-
try (var classLoader = new URLClassLoader(new URL[] { url }, current)) {
440-
Thread.currentThread().setContextClassLoader(classLoader);
441-
runnable.run();
442-
}
443-
catch (IOException e) {
444-
throw new UncheckedIOException(e);
445-
}
446-
finally {
447-
Thread.currentThread().setContextClassLoader(current);
448-
}
434+
ClasspathRunner.withClasspath("testservices/", runnable);
449435
}
450436

451437
private LauncherDiscoveryRequest createLauncherDiscoveryRequestForBothStandardEngineExampleClasses() {

0 commit comments

Comments
 (0)