Skip to content

Commit e5f9509

Browse files
committed
Validate KitchenSinkExtension for completeness
1 parent 2cdd597 commit e5f9509

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/ExtensionComposabilityTests.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,22 @@
1414
import static java.util.stream.Collectors.toList;
1515
import static org.assertj.core.api.Assertions.assertThat;
1616
import static org.junit.jupiter.api.Assertions.assertAll;
17+
import static org.junit.jupiter.api.Assertions.assertTrue;
18+
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
19+
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
1720
import static org.junit.platform.commons.util.FunctionUtils.where;
1821

1922
import java.lang.reflect.Method;
2023
import java.lang.reflect.Modifier;
2124
import java.lang.reflect.Proxy;
2225
import java.util.Arrays;
2326
import java.util.List;
27+
import java.util.stream.Stream;
2428

29+
import org.junit.jupiter.api.DynamicContainer;
2530
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.api.TestFactory;
32+
import org.junit.platform.commons.support.ModifierSupport;
2633
import org.junit.platform.commons.util.ClassUtils;
2734
import org.junit.platform.commons.util.ReflectionUtils;
2835

@@ -43,8 +50,7 @@ class ExtensionComposabilityTests {
4350
void ensureJupiterExtensionApisAreComposable() {
4451

4552
// 1) Find all existing top-level Extension APIs
46-
List<Class<?>> extensionApis = ReflectionUtils.findAllClassesInPackage(Extension.class.getPackage().getName(),
47-
this::isExtensionApi, name -> true);
53+
List<Class<?>> extensionApis = findExtensionApis();
4854

4955
// 2) Determine which methods we expect the kitchen sink to implement...
5056

@@ -110,6 +116,34 @@ void ensureJupiterExtensionApisAreComposable() {
110116
// @formatter:on
111117
}
112118

119+
@TestFactory
120+
Stream<DynamicContainer> kitchenSinkExtensionImplementsAllExtensionApis() {
121+
var declaredMethods = List.of(KitchenSinkExtension.class.getDeclaredMethods());
122+
return findExtensionApis().stream() //
123+
.map(c -> dynamicContainer( //
124+
c.getSimpleName(), //
125+
Stream.concat( //
126+
Stream.of(
127+
dynamicTest("implements interface", () -> c.isAssignableFrom(KitchenSinkExtension.class))), //
128+
Arrays.stream(c.getMethods()) //
129+
.filter(ModifierSupport::isNotStatic).map(m -> dynamicTest( //
130+
"overrides " + m.getName(), //
131+
() -> assertTrue( //
132+
declaredMethods.stream().anyMatch(it -> //
133+
it.getName().equals(m.getName()) //
134+
&& it.getReturnType().equals(m.getReturnType()) //
135+
&& Arrays.equals(it.getParameterTypes(), m.getParameterTypes()) //
136+
))) //
137+
) //
138+
) //
139+
));
140+
}
141+
142+
private List<Class<?>> findExtensionApis() {
143+
return ReflectionUtils.findAllClassesInPackage(Extension.class.getPackage().getName(), this::isExtensionApi,
144+
name -> true);
145+
}
146+
113147
private boolean isExtensionApi(Class<?> candidate) {
114148
return candidate.isInterface() && (candidate != Extension.class) && Extension.class.isAssignableFrom(candidate);
115149
}

junit-jupiter-engine/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
package org.junit.jupiter.api.extension;
1212

13+
import java.lang.reflect.Constructor;
14+
import java.lang.reflect.Method;
1315
import java.util.Optional;
1416
import java.util.stream.Stream;
1517

@@ -177,4 +179,67 @@ public void testAborted(ExtensionContext context, Throwable cause) {
177179
public void testFailed(ExtensionContext context, Throwable cause) {
178180
}
179181

182+
// --- InvocationInterceptor -----------------------------------------------
183+
184+
@Override
185+
public <T> T interceptTestClassConstructor(Invocation<T> invocation,
186+
ReflectiveInvocationContext<Constructor<T>> invocationContext, ExtensionContext extensionContext)
187+
throws Throwable {
188+
return InvocationInterceptor.super.interceptTestClassConstructor(invocation, invocationContext,
189+
extensionContext);
190+
}
191+
192+
@Override
193+
public void interceptBeforeAllMethod(Invocation<Void> invocation,
194+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
195+
InvocationInterceptor.super.interceptBeforeAllMethod(invocation, invocationContext, extensionContext);
196+
}
197+
198+
@Override
199+
public void interceptBeforeEachMethod(Invocation<Void> invocation,
200+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
201+
InvocationInterceptor.super.interceptBeforeEachMethod(invocation, invocationContext, extensionContext);
202+
}
203+
204+
@Override
205+
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
206+
ExtensionContext extensionContext) throws Throwable {
207+
InvocationInterceptor.super.interceptTestMethod(invocation, invocationContext, extensionContext);
208+
}
209+
210+
@Override
211+
public <T> T interceptTestFactoryMethod(Invocation<T> invocation,
212+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
213+
return InvocationInterceptor.super.interceptTestFactoryMethod(invocation, invocationContext, extensionContext);
214+
}
215+
216+
@Override
217+
public void interceptTestTemplateMethod(Invocation<Void> invocation,
218+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
219+
InvocationInterceptor.super.interceptTestTemplateMethod(invocation, invocationContext, extensionContext);
220+
}
221+
222+
@SuppressWarnings("deprecation")
223+
@Override
224+
public void interceptDynamicTest(Invocation<Void> invocation, ExtensionContext extensionContext) throws Throwable {
225+
InvocationInterceptor.super.interceptDynamicTest(invocation, extensionContext);
226+
}
227+
228+
@Override
229+
public void interceptDynamicTest(Invocation<Void> invocation, DynamicTestInvocationContext invocationContext,
230+
ExtensionContext extensionContext) throws Throwable {
231+
InvocationInterceptor.super.interceptDynamicTest(invocation, invocationContext, extensionContext);
232+
}
233+
234+
@Override
235+
public void interceptAfterEachMethod(Invocation<Void> invocation,
236+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
237+
InvocationInterceptor.super.interceptAfterEachMethod(invocation, invocationContext, extensionContext);
238+
}
239+
240+
@Override
241+
public void interceptAfterAllMethod(Invocation<Void> invocation,
242+
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
243+
InvocationInterceptor.super.interceptAfterAllMethod(invocation, invocationContext, extensionContext);
244+
}
180245
}

0 commit comments

Comments
 (0)