1010
1111package org .junit .jupiter .engine .support ;
1212
13+ import static org .assertj .core .api .Assertions .assertThat ;
1314import static org .junit .jupiter .api .Assertions .assertNotNull ;
1415import static org .junit .jupiter .api .Assertions .assertThrows ;
1516
1617import java .net .URL ;
1718import java .net .URLClassLoader ;
19+ import java .util .logging .Level ;
20+ import java .util .logging .LogRecord ;
1821
1922import org .junit .internal .AssumptionViolatedException ;
2023import org .junit .jupiter .api .Test ;
24+ import org .junit .jupiter .api .function .Executable ;
25+ import org .junit .jupiter .engine .TrackLogRecords ;
26+ import org .junit .platform .commons .logging .LogRecordListener ;
2127import org .junit .platform .commons .util .ReflectionUtils ;
2228
2329/**
2430 * Unit tests for {@link OpenTest4JAndJUnit4AwareThrowableCollector}.
2531 *
2632 * @since 5.5.2
2733 */
34+ @ TrackLogRecords
2835class OpenTest4JAndJUnit4AwareThrowableCollectorTests {
2936
3037 @ Test
31- void simulateHamcrestNotInTheClasspath () throws Exception {
32- ClassLoader originalClassLoader = Thread .currentThread ().getContextClassLoader ();
33- try {
34- HamcrestHidingClassLoader classLoader = new HamcrestHidingClassLoader ();
38+ void simulateJUnit4NotInTheClasspath (LogRecordListener listener ) throws Throwable {
39+ TestClassLoader classLoader = new TestClassLoader (true , false );
3540
36- // We have to set our custom ClassLoader as the TCCL so that
37- // ReflectionUtils uses it (indirectly via ClassLoaderUtils).
38- Thread .currentThread ().setContextClassLoader (classLoader );
41+ doWithCustomClassLoader (classLoader , () -> {
42+ // Ensure that our custom ClassLoader actually throws a ClassNotFoundException
43+ // when attempting to load the AssumptionViolatedException class.
44+ assertThrows (ClassNotFoundException .class ,
45+ () -> ReflectionUtils .tryToLoadClass (AssumptionViolatedException .class .getName ()).get ());
46+
47+ Class <?> clazz = classLoader .loadClass (OpenTest4JAndJUnit4AwareThrowableCollector .class .getName ());
48+ assertNotNull (ReflectionUtils .newInstance (clazz ));
49+
50+ // @formatter:off
51+ assertThat (listener .stream (Level .FINE ).map (LogRecord ::getMessage ).findFirst ().orElse ("<not found>" ))
52+ .isEqualTo (
53+ "Failed to load class org.junit.internal.AssumptionViolatedException: " +
54+ "only supporting org.opentest4j.TestAbortedException for aborted execution." );
55+ // @formatter:on
56+ });
57+ }
58+
59+ @ Test
60+ void simulateHamcrestNotInTheClasspath (LogRecordListener listener ) throws Throwable {
61+ TestClassLoader classLoader = new TestClassLoader (false , true );
3962
63+ doWithCustomClassLoader (classLoader , () -> {
4064 // Ensure that our custom ClassLoader actually throws a NoClassDefFoundError
4165 // when attempting to load the AssumptionViolatedException class.
4266 assertThrows (NoClassDefFoundError .class ,
43- () -> ReflectionUtils .tryToLoadClass (AssumptionViolatedException .class .getName ()));
67+ () -> ReflectionUtils .tryToLoadClass (AssumptionViolatedException .class .getName ()). get () );
4468
4569 Class <?> clazz = classLoader .loadClass (OpenTest4JAndJUnit4AwareThrowableCollector .class .getName ());
4670 assertNotNull (ReflectionUtils .newInstance (clazz ));
71+
72+ // @formatter:off
73+ assertThat (listener .stream (Level .INFO ).map (LogRecord ::getMessage ).findFirst ().orElse ("<not found>" ))
74+ .isEqualTo (
75+ "Failed to load class org.junit.internal.AssumptionViolatedException: " +
76+ "only supporting org.opentest4j.TestAbortedException for aborted execution. " +
77+ "Note that org.junit.internal.AssumptionViolatedException requires that Hamcrest is on the classpath." );
78+ // @formatter:on
79+ });
80+ }
81+
82+ private void doWithCustomClassLoader (ClassLoader classLoader , Executable executable ) throws Throwable {
83+ ClassLoader originalClassLoader = Thread .currentThread ().getContextClassLoader ();
84+ try {
85+ // We have to set our custom ClassLoader as the TCCL so that
86+ // ReflectionUtils uses it (indirectly via ClassLoaderUtils).
87+ Thread .currentThread ().setContextClassLoader (classLoader );
88+
89+ executable .execute ();
4790 }
4891 finally {
4992 Thread .currentThread ().setContextClassLoader (originalClassLoader );
5093 }
5194 }
5295
53- private static class HamcrestHidingClassLoader extends URLClassLoader {
96+ private static class TestClassLoader extends URLClassLoader {
97+
98+ private static URL [] CLASSPATH_URLS = new URL [] {
99+ OpenTest4JAndJUnit4AwareThrowableCollector .class .getProtectionDomain ().getCodeSource ().getLocation () };
54100
55- HamcrestHidingClassLoader () {
56- super (new URL [] {
57- OpenTest4JAndJUnit4AwareThrowableCollector .class .getProtectionDomain ().getCodeSource ().getLocation () },
58- getSystemClassLoader ());
101+ private final boolean simulateJUnit4Missing ;
102+ private final boolean simulateHamcrestMissing ;
103+
104+ public TestClassLoader (boolean simulateJUnit4Missing , boolean simulateHamcrestMissing ) {
105+ super (CLASSPATH_URLS , getSystemClassLoader ());
106+ this .simulateJUnit4Missing = simulateJUnit4Missing ;
107+ this .simulateHamcrestMissing = simulateHamcrestMissing ;
59108 }
60109
61110 @ Override
@@ -66,8 +115,13 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
66115 return findClass (name );
67116 }
68117
118+ // Simulate that JUnit 4 is not in the classpath when loading AssumptionViolatedException
119+ if (this .simulateJUnit4Missing && name .equals (AssumptionViolatedException .class .getName ())) {
120+ throw new ClassNotFoundException (AssumptionViolatedException .class .getName ());
121+ }
122+
69123 // Simulate that Hamcrest is not in the classpath when loading AssumptionViolatedException
70- if (name .equals (AssumptionViolatedException .class .getName ())) {
124+ if (this . simulateHamcrestMissing && name .equals (AssumptionViolatedException .class .getName ())) {
71125 throw new NoClassDefFoundError ("org/hamcrest/SelfDescribing" );
72126 }
73127
0 commit comments