|
17 | 17 |
|
18 | 18 | import io.github.scordio.junit.converters.SpringConversion; |
19 | 19 | import org.junit.jupiter.api.Test; |
| 20 | +import org.junit.jupiter.api.extension.ParameterResolutionException; |
20 | 21 | import org.junit.jupiter.params.ParameterizedTest; |
21 | 22 | import org.junit.jupiter.params.provider.FieldSource; |
| 23 | +import org.junit.jupiter.params.provider.ValueSource; |
22 | 24 |
|
| 25 | +import java.net.URL; |
| 26 | +import java.net.URLClassLoader; |
| 27 | +import java.security.CodeSource; |
| 28 | +import java.security.ProtectionDomain; |
23 | 29 | import java.util.List; |
24 | 30 | import java.util.Map; |
| 31 | +import java.util.Set; |
| 32 | +import java.util.stream.Collectors; |
25 | 33 |
|
26 | 34 | import static io.github.scordio.tests.junit.converters.JupiterEngineTestKit.executeTestsForClass; |
27 | 35 | import static org.assertj.core.api.Assertions.assertThat; |
28 | 36 | import static org.junit.jupiter.params.provider.Arguments.arguments; |
| 37 | +import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; |
| 38 | +import static org.junit.platform.testkit.engine.TestExecutionResultConditions.cause; |
| 39 | +import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; |
| 40 | +import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; |
29 | 41 |
|
30 | 42 | class SpringConversionIntegrationTests { |
31 | 43 |
|
@@ -104,4 +116,65 @@ void string_to_list(@SpringConversion List<Integer> list, List<Integer> expected |
104 | 116 |
|
105 | 117 | } |
106 | 118 |
|
| 119 | + @Test |
| 120 | + void should_fail_without_spring_core_in_the_classpath() { |
| 121 | + ClassLoader classLoader = new SpringFilteringClassLoader(); |
| 122 | + |
| 123 | + executeTestsForClass(MissingSpringCoreTestCase.class.getName(), classLoader).testEvents() |
| 124 | + .assertStatistics(stats -> stats.started(1).failed(1)) |
| 125 | + .assertThatEvents() |
| 126 | + .haveExactly(1, finishedWithFailure( // |
| 127 | + instanceOf(ParameterResolutionException.class), cause( // |
| 128 | + instanceOf(NoClassDefFoundError.class), |
| 129 | + message("org/springframework/core/convert/ConversionService")))); |
| 130 | + } |
| 131 | + |
| 132 | + static class MissingSpringCoreTestCase { |
| 133 | + |
| 134 | + @ParameterizedTest |
| 135 | + @ValueSource(strings = "123, 456") |
| 136 | + void test(@SuppressWarnings("unused") @SpringConversion List<Integer> list) { |
| 137 | + // never called |
| 138 | + } |
| 139 | + |
| 140 | + } |
| 141 | + |
| 142 | + private static class SpringFilteringClassLoader extends URLClassLoader { |
| 143 | + |
| 144 | + private static final Set<Class<?>> TARGET_CLASSES = Set.of( // |
| 145 | + MissingSpringCoreTestCase.class, SpringConversion.class); |
| 146 | + |
| 147 | + private static final Set<String> TARGET_PACKAGES = TARGET_CLASSES.stream() |
| 148 | + .map(Class::getPackageName) |
| 149 | + .collect(Collectors.toSet()); |
| 150 | + |
| 151 | + private static final URL[] CLASSPATH_URLS = TARGET_CLASSES.stream() |
| 152 | + .map(Class::getProtectionDomain) |
| 153 | + .map(ProtectionDomain::getCodeSource) |
| 154 | + .map(CodeSource::getLocation) |
| 155 | + .toArray(URL[]::new); |
| 156 | + |
| 157 | + private static final String SPRING_CORE_PACKAGE = "org.springframework.core"; |
| 158 | + |
| 159 | + private SpringFilteringClassLoader() { |
| 160 | + super(CLASSPATH_URLS); |
| 161 | + } |
| 162 | + |
| 163 | + @Override |
| 164 | + public Class<?> loadClass(String name) throws ClassNotFoundException { |
| 165 | + synchronized (getClassLoadingLock(name)) { |
| 166 | + if (TARGET_PACKAGES.stream().anyMatch(name::startsWith)) { |
| 167 | + return findClass(name); |
| 168 | + } |
| 169 | + |
| 170 | + if (name.startsWith(SPRING_CORE_PACKAGE)) { |
| 171 | + throw new ClassNotFoundException(); |
| 172 | + } |
| 173 | + |
| 174 | + return super.loadClass(name); |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + } |
| 179 | + |
107 | 180 | } |
0 commit comments