Skip to content

Commit ed2b812

Browse files
committed
Add tests for extension context scope supplied to InvocationInterceptor
1 parent b083686 commit ed2b812

File tree

1 file changed

+85
-17
lines changed

1 file changed

+85
-17
lines changed

jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/InvocationInterceptorTests.java

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

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

13+
import static java.util.function.Function.identity;
14+
import static java.util.function.Predicate.isEqual;
1315
import static org.assertj.core.api.Assertions.assertThat;
1416
import static org.junit.jupiter.api.Assertions.assertEquals;
1517
import static org.junit.jupiter.api.Assertions.fail;
@@ -22,17 +24,23 @@
2224

2325
import java.lang.reflect.Constructor;
2426
import java.lang.reflect.Method;
25-
import java.util.EnumSet;
27+
import java.util.Arrays;
28+
import java.util.Collection;
29+
import java.util.List;
30+
import java.util.function.UnaryOperator;
2631
import java.util.stream.Stream;
2732

2833
import org.junit.jupiter.api.AfterAll;
2934
import org.junit.jupiter.api.AfterEach;
3035
import org.junit.jupiter.api.BeforeAll;
3136
import org.junit.jupiter.api.BeforeEach;
3237
import org.junit.jupiter.api.DynamicTest;
38+
import org.junit.jupiter.api.MethodOrderer;
39+
import org.junit.jupiter.api.Order;
3340
import org.junit.jupiter.api.RepeatedTest;
3441
import org.junit.jupiter.api.Test;
3542
import org.junit.jupiter.api.TestFactory;
43+
import org.junit.jupiter.api.TestMethodOrder;
3644
import org.junit.jupiter.api.TestReporter;
3745
import org.junit.jupiter.api.extension.DynamicTestInvocationContext;
3846
import org.junit.jupiter.api.extension.ExtendWith;
@@ -42,8 +50,6 @@
4250
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
4351
import org.junit.jupiter.api.extension.RegisterExtension;
4452
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests;
45-
import org.junit.jupiter.params.ParameterizedTest;
46-
import org.junit.jupiter.params.provider.EnumSource;
4753
import org.junit.platform.commons.JUnitException;
4854
import org.junit.platform.engine.reporting.ReportEntry;
4955
import org.junit.platform.testkit.engine.EngineExecutionResults;
@@ -130,28 +136,76 @@ void test() {
130136
}
131137
}
132138

133-
@ParameterizedTest(name = "{0}")
134-
@EnumSource(InvocationType.class)
135-
void callsInterceptors(InvocationType invocationType) {
139+
@TestFactory
140+
Stream<DynamicTest> callsInterceptors() {
136141
var results = executeTestsForClass(TestCaseWithThreeInterceptors.class);
137142

138143
results.testEvents().assertStatistics(stats -> stats.failed(0).succeeded(3));
139144

140-
assertThat(getEvents(results, EnumSet.of(invocationType)).distinct()) //
141-
.containsExactly("before:foo", "before:bar", "before:baz", "test", "after:baz", "after:bar",
142-
"after:foo");
145+
return Arrays.stream(InvocationType.values()) //
146+
.map(it -> dynamicTest(it.name(), () -> verifyEvents(results, it)));
143147
}
144148

145-
private Stream<String> getEvents(EngineExecutionResults results, EnumSet<InvocationType> types) {
146-
return results.allEvents().reportingEntryPublished() //
147-
.map(event -> event.getPayload(ReportEntry.class).orElseThrow()) //
148-
.map(ReportEntry::getKeyValuePairs) //
149-
.filter(map -> map.keySet().stream().map(InvocationType::valueOf).anyMatch(types::contains)) //
150-
.flatMap(map -> map.values().stream());
149+
private void verifyEvents(EngineExecutionResults results, InvocationType invocationType) {
150+
var beforeEvents = List.of("before:foo", "before:bar", "before:baz");
151+
var testEvent = List.of("test");
152+
var afterEvents = List.of("after:baz", "after:bar", "after:foo");
153+
var allEvents = Stream.of(beforeEvents, testEvent, afterEvents).flatMap(Collection::stream).toList();
154+
String testClassName = TestCaseWithThreeInterceptors.class.getName();
155+
156+
var expectedElements = switch (invocationType) {
157+
case BEFORE_ALL, AFTER_ALL -> prefixed(allEvents, testClassName);
158+
case CONSTRUCTOR -> concatStreams(
159+
prefixed(allEvents, it -> it.endsWith(":bar") ? testClassName : "test(TestReporter)"),
160+
prefixed(allEvents, it -> it.endsWith(":bar") ? testClassName : "testTemplate(TestReporter)[1]"),
161+
prefixed(allEvents, it -> it.endsWith(":bar") ? testClassName : "testFactory(TestReporter)"));
162+
case BEFORE_EACH, AFTER_EACH -> concatStreams(prefixed(allEvents, "test(TestReporter)"),
163+
prefixed(allEvents, "testTemplate(TestReporter)[1]"), prefixed(allEvents, "testFactory(TestReporter)"));
164+
case TEST_METHOD -> prefixed(allEvents, "test(TestReporter)");
165+
case TEST_TEMPLATE_METHOD -> prefixed(allEvents, "testTemplate(TestReporter)[1]");
166+
case TEST_FACTORY_METHOD -> prefixed(allEvents, "testFactory(TestReporter)");
167+
case DYNAMIC_TEST -> concatStreams(prefixed(beforeEvents, "testFactory(TestReporter)[1]"),
168+
prefixed(testEvent, "testFactory(TestReporter)"),
169+
prefixed(afterEvents, "testFactory(TestReporter)[1]"));
170+
};
171+
172+
assertThat(getEvents(results, invocationType)) //
173+
.containsExactlyElementsOf(expectedElements.toList());
174+
}
175+
176+
@SafeVarargs
177+
@SuppressWarnings("varargs")
178+
private static <T> Stream<T> concatStreams(Stream<T>... items) {
179+
return Stream.of(items).flatMap(identity());
180+
}
181+
182+
private static Stream<String> prefixed(List<String> values, String prefix) {
183+
return prefixed(values, __ -> prefix);
184+
}
185+
186+
private static Stream<String> prefixed(List<String> values, UnaryOperator<String> prefixGenerator) {
187+
return values.stream() //
188+
.map(it -> "[%s] %s".formatted(prefixGenerator.apply(it), it));
189+
}
190+
191+
private Stream<String> getEvents(EngineExecutionResults results, InvocationType invocationType) {
192+
return results.allEvents().reportingEntryPublished().stream() //
193+
.flatMap(event -> {
194+
var reportEntry = event.getPayload(ReportEntry.class).orElseThrow();
195+
var keyValuePairs = reportEntry.getKeyValuePairs();
196+
if (keyValuePairs.keySet().stream() //
197+
.map(InvocationType::valueOf) //
198+
.anyMatch(isEqual(invocationType))) {
199+
return keyValuePairs.values().stream() //
200+
.map(it -> "[%s] %s".formatted(event.getTestDescriptor().getLegacyReportingName(), it));
201+
}
202+
return Stream.empty();
203+
});
151204
}
152205

153206
@SuppressWarnings("JUnitMalformedDeclaration")
154207
@ExtendWith({ FooInvocationInterceptor.class, BarInvocationInterceptor.class, BazInvocationInterceptor.class })
208+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
155209
static class TestCaseWithThreeInterceptors {
156210

157211
public TestCaseWithThreeInterceptors(TestReporter reporter) {
@@ -169,16 +223,19 @@ void beforeEach(TestReporter reporter) {
169223
publish(reporter, InvocationType.BEFORE_EACH);
170224
}
171225

226+
@Order(1)
172227
@Test
173228
void test(TestReporter reporter) {
174229
publish(reporter, InvocationType.TEST_METHOD);
175230
}
176231

232+
@Order(2)
177233
@RepeatedTest(1)
178234
void testTemplate(TestReporter reporter) {
179235
publish(reporter, InvocationType.TEST_TEMPLATE_METHOD);
180236
}
181237

238+
@Order(3)
182239
@TestFactory
183240
DynamicTest testFactory(TestReporter reporter) {
184241
publish(reporter, InvocationType.TEST_FACTORY_METHOD);
@@ -224,6 +281,11 @@ abstract static class ReportingInvocationInterceptor implements InvocationInterc
224281
this.name = name;
225282
}
226283

284+
@Override
285+
public ExtensionContextScope getTestInstantiationExtensionContextScope(ExtensionContext rootContext) {
286+
return ExtensionContextScope.TEST_METHOD;
287+
}
288+
227289
@Override
228290
public void interceptBeforeAllMethod(Invocation<Void> invocation,
229291
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext)
@@ -299,8 +361,8 @@ public void interceptDynamicTest(Invocation<Void> invocation, DynamicTestInvocat
299361
assertThat(invocationContext.getExecutable()).isNotNull();
300362
assertThat(extensionContext.getUniqueId()).isNotBlank();
301363
assertThat(extensionContext.getElement()).isEmpty();
302-
assertThat(extensionContext.getParent().flatMap(ExtensionContext::getTestMethod)).contains(
303-
testClass.getDeclaredMethod("testFactory", TestReporter.class));
364+
assertThat(extensionContext.getParent().flatMap(ExtensionContext::getTestMethod)) //
365+
.contains(testClass.getDeclaredMethod("testFactory", TestReporter.class));
304366
reportAndProceed(invocation, extensionContext, InvocationType.DYNAMIC_TEST);
305367
}
306368

@@ -350,6 +412,12 @@ static class BarInvocationInterceptor extends ReportingInvocationInterceptor {
350412
BarInvocationInterceptor() {
351413
super("bar");
352414
}
415+
416+
@SuppressWarnings("deprecation")
417+
@Override
418+
public ExtensionContextScope getTestInstantiationExtensionContextScope(ExtensionContext rootContext) {
419+
return ExtensionContextScope.DEFAULT;
420+
}
353421
}
354422

355423
static class BazInvocationInterceptor extends ReportingInvocationInterceptor {

0 commit comments

Comments
 (0)