Skip to content

Commit f149ad6

Browse files
committed
Allow @RegisterExtension/@ExtendWith fields to be sorted relative to each other
Prior to this commit, @ExtendWith fields and @RegisterExtension fields were sorted using @order, but extensions registered via @ExtendWith fields were always registered first (before extensions registered via @RegisterExtension fields). This commit ensures that @RegisterExtension fields and @ExtendWith fields are sorted via @order relative to each other. See #864, #2680
1 parent cc9690b commit f149ad6

File tree

2 files changed

+37
-40
lines changed

2 files changed

+37
-40
lines changed

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.lang.reflect.AnnotatedElement;
2222
import java.lang.reflect.Executable;
2323
import java.lang.reflect.Field;
24-
import java.util.ArrayList;
2524
import java.util.Arrays;
2625
import java.util.Comparator;
2726
import java.util.List;
@@ -93,28 +92,24 @@ static void registerExtensionsFromFields(ExtensionRegistrar registrar, Class<?>
9392

9493
Predicate<Field> predicate = (instance == null ? ReflectionUtils::isStatic : ReflectionUtils::isNotStatic);
9594

96-
// Ensure that the list is modifiable, since findFields() returns an unmodifiable list.
97-
List<Field> fields = new ArrayList<>(findFields(clazz, predicate, TOP_DOWN));
98-
99-
// Sort fields based on @Order.
100-
fields.sort(orderComparator);
101-
102-
// @formatter:off
103-
fields.stream()
104-
.flatMap(ExtensionUtils::streamExtensionTypes)
105-
.forEach(registrar::registerExtension);
106-
107-
fields.stream()
108-
.filter(field -> isAnnotated(field, RegisterExtension.class))
109-
.forEach(field -> {
110-
tryToReadFieldValue(field, instance).ifSuccess(value -> {
111-
Preconditions.condition(value instanceof Extension, () -> String.format(
112-
"Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.",
113-
field, (value != null ? value.getClass().getName() : null), Extension.class.getName()));
114-
registrar.registerExtension((Extension) value, field);
95+
findFields(clazz, predicate, TOP_DOWN).stream()//
96+
.sorted(orderComparator)//
97+
.forEach(field -> {
98+
List<ExtendWith> extendWithAnnotations = findRepeatableAnnotations(field, ExtendWith.class);
99+
boolean isExtendWithPresent = !extendWithAnnotations.isEmpty();
100+
boolean isRegisterExtensionPresent = isAnnotated(field, RegisterExtension.class);
101+
if (isExtendWithPresent) {
102+
streamExtensionTypes(extendWithAnnotations).forEach(registrar::registerExtension);
103+
}
104+
if (isRegisterExtensionPresent) {
105+
tryToReadFieldValue(field, instance).ifSuccess(value -> {
106+
Preconditions.condition(value instanceof Extension, () -> String.format(
107+
"Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.",
108+
field, (value != null ? value.getClass().getName() : null), Extension.class.getName()));
109+
registrar.registerExtension((Extension) value, field);
110+
});
111+
}
115112
});
116-
});
117-
// @formatter:on
118113
}
119114

120115
/**

junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -139,39 +139,39 @@ void registrationOrder(LogRecordListener listener) {
139139
assertOneTestSucceeded(AllInOneWithTestInstancePerMethodTestCase.class);
140140
assertThat(getRegisteredLocalExtensions(listener))//
141141
.containsExactly(//
142-
"StaticField1", // @ExtendWith on static field
142+
"ClassLevelExtension2", // @RegisterExtension on static field
143143
"StaticField2", // @ExtendWith on static field
144144
"ClassLevelExtension1", // @RegisterExtension on static field
145-
"ClassLevelExtension2", // @RegisterExtension on static field
145+
"StaticField1", // @ExtendWith on static field
146146
"ConstructorParameter", // @ExtendWith on parameter in constructor
147147
"BeforeAllParameter", // @ExtendWith on parameter in static @BeforeAll method
148148
"BeforeEachParameter", // @ExtendWith on parameter in @BeforeEach method
149149
"AfterEachParameter", // @ExtendWith on parameter in @AfterEach method
150150
"AfterAllParameter", // @ExtendWith on parameter in static @AfterAll method
151151
"TestParameter", // @ExtendWith on parameter in @Test method
152-
"InstanceField1", // @ExtendWith on instance field
153-
"InstanceField2", // @ExtendWith on instance field
154152
"InstanceLevelExtension1", // @RegisterExtension on instance field
155-
"InstanceLevelExtension2"// @RegisterExtension on instance field
153+
"InstanceField1", // @ExtendWith on instance field
154+
"InstanceLevelExtension2", // @RegisterExtension on instance field
155+
"InstanceField2" // @ExtendWith on instance field
156156
);
157157

158158
listener.clear();
159159
assertOneTestSucceeded(AllInOneWithTestInstancePerClassTestCase.class);
160160
assertThat(getRegisteredLocalExtensions(listener))//
161161
.containsExactly(//
162-
"StaticField1", // @ExtendWith on static field
162+
"ClassLevelExtension2", // @RegisterExtension on static field
163163
"StaticField2", // @ExtendWith on static field
164164
"ClassLevelExtension1", // @RegisterExtension on static field
165-
"ClassLevelExtension2", // @RegisterExtension on static field
165+
"StaticField1", // @ExtendWith on static field
166166
"ConstructorParameter", // @ExtendWith on parameter in constructor
167167
"BeforeAllParameter", // @ExtendWith on parameter in static @BeforeAll method
168168
"BeforeEachParameter", // @ExtendWith on parameter in @BeforeEach method
169169
"AfterEachParameter", // @ExtendWith on parameter in @AfterEach method
170170
"AfterAllParameter", // @ExtendWith on parameter in static @AfterAll method
171-
"InstanceField1", // @ExtendWith on instance field
172-
"InstanceField2", // @ExtendWith on instance field
173171
"InstanceLevelExtension1", // @RegisterExtension on instance field
172+
"InstanceField1", // @ExtendWith on instance field
174173
"InstanceLevelExtension2", // @RegisterExtension on instance field
174+
"InstanceField2", // @ExtendWith on instance field
175175
"TestParameter" // @ExtendWith on parameter in @Test method
176176
);
177177
}
@@ -603,33 +603,35 @@ void test() {
603603
static class AllInOneWithTestInstancePerMethodTestCase {
604604

605605
@StaticField1
606+
@Order(Integer.MAX_VALUE)
606607
static String staticField1;
607608

608609
@StaticField2
609610
@ExtendWith(StaticField2.Extension.class)
611+
@Order(3)
610612
static String staticField2;
611613

614+
@RegisterExtension
615+
private static Extension classLevelExtension1 = new ClassLevelExtension1();
616+
617+
@RegisterExtension
618+
@Order(1)
619+
static Extension classLevelExtension2 = new ClassLevelExtension2();
620+
612621
@InstanceField1
622+
@Order(2)
613623
String instanceField1;
614624

615625
@InstanceField2
616626
@ExtendWith(InstanceField2.Extension.class)
617627
String instanceField2;
618628

619-
@RegisterExtension
620-
@Order(1)
621-
private static Extension classLevelExtension1 = new ClassLevelExtension1();
622-
623-
@RegisterExtension
624-
@Order(2)
625-
static Extension classLevelExtension2 = new ClassLevelExtension2();
626-
627629
@RegisterExtension
628630
@Order(1)
629631
private Extension instanceLevelExtension1 = new InstanceLevelExtension1();
630632

631633
@RegisterExtension
632-
@Order(2)
634+
@Order(3)
633635
Extension instanceLevelExtension2 = new InstanceLevelExtension2();
634636

635637
AllInOneWithTestInstancePerMethodTestCase(@ConstructorParameter String text) {

0 commit comments

Comments
 (0)