Skip to content

Commit 656b9ed

Browse files
committed
Document method and field inheritance semantics
See #3553
1 parent ef17fc0 commit 656b9ed

File tree

17 files changed

+223
-97
lines changed

17 files changed

+223
-97
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.11.0-M1.adoc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ repository on GitHub.
1616
[[release-notes-5.11.0-M1-junit-platform-bug-fixes]]
1717
==== Bug Fixes
1818

19+
* Field and method search algorithms now adhere to standard Java semantics regarding
20+
whether a given field or method is visible or overridden according to the rules of the
21+
Java language. See the new
22+
<<../user-guide/index.adoc#extensions-supported-utilities-search-semantics, Field and
23+
Method Search Semantics>> section of the User Guide for details.
1924
* `ReflectionSupport.findFields(...)` now returns a distinct set of fields.
2025
* Fixed parsing of recursive jar URIs which allows the JUnit Platform Launcher to be used
2126
inside Spring Boot executable jars for Spring Boot 3.2 and later.
@@ -25,7 +30,13 @@ repository on GitHub.
2530
[[release-notes-5.11.0-M1-junit-platform-deprecations-and-breaking-changes]]
2631
==== Deprecations and Breaking Changes
2732

28-
* ❓
33+
* As mentioned in the _Bug Fixes_ section above, field and method search algorithms now
34+
adhere to standard Java semantics regarding whether a given field or method is visible
35+
or overridden according to the rules of the Java language. The changes in the search
36+
algorithms may, however, result in breaking changes for some use cases. In light of
37+
that, it is possible to revert to the previous "legacy semantics". See the new
38+
<<../user-guide/index.adoc#extensions-supported-utilities-search-semantics, Field and
39+
Method Search Semantics>> section of the User Guide for details.
2940

3041
[[release-notes-5.11.0-M1-junit-platform-new-features-and-improvements]]
3142
==== New Features and Improvements
@@ -43,7 +54,19 @@ repository on GitHub.
4354
[[release-notes-5.11.0-M1-junit-jupiter-bug-fixes]]
4455
==== Bug Fixes
4556

46-
* ❓
57+
* Due to changes in the JUnit Platform regarding field and method search algorithms (see
58+
<<release-notes-5.11.0-M1-junit-platform-bug-fixes>> above), numerous bugs have been
59+
addressed within JUnit Jupiter, including but not limited to the following.
60+
** Two `@TempDir` fields with the same name in a superclass and subclass will now both
61+
be injected.
62+
** Two `@Test` methods with the same signature in a superclass and subclass will now
63+
both be invoked, as long as the `@Test` method in the subclass does not override the
64+
`@Test` method in the superclass, which can occur if the superclass method is `private`
65+
or if the superclass method is package-private and resides in a different package than
66+
the subclass.
67+
*** The same applies to other types of test methods (`@TestFactory`,
68+
`@ParameterizedTest`, etc.) as well as lifecycle methods (`@BeforeAll`,
69+
`@AfterAll`, `@BeforeEach`, and `@AfterEach`).
4770

4871
[[release-notes-5.11.0-M1-junit-jupiter-deprecations-and-breaking-changes]]
4972
==== Deprecations and Breaking Changes

documentation/src/docs/asciidoc/user-guide/extensions.adoc

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,15 @@ using the `@Order` annotation. See the <<extensions-registration-programmatic-or
156156
Extension Registration Order>> tip for `@RegisterExtension` fields for details.
157157
====
158158

159+
[TIP]
160+
.Extension Inheritance
161+
====
162+
Extensions registered declaratively via `@ExtendWith` on fields in superclasses will be
163+
inherited.
164+
165+
See <<extensions-registration-inheritance, Extension Inheritance>> for details.
166+
====
167+
159168
NOTE: `@ExtendWith` fields may be either `static` or non-static. The documentation on
160169
<<extensions-registration-programmatic-static-fields, Static Fields>> and
161170
<<extensions-registration-programmatic-instance-fields, Instance Fields>> for
@@ -196,6 +205,15 @@ extensions to be registered last and _after_ callback extensions to be registere
196205
relative to other programmatically registered extensions.
197206
====
198207

208+
[TIP]
209+
.Extension Inheritance
210+
====
211+
Extensions registered via `@RegisterExtension` or `@ExtendWith` on fields in superclasses
212+
will be inherited.
213+
214+
See <<extensions-registration-inheritance, Extension Inheritance>> for details.
215+
====
216+
199217
NOTE: `@RegisterExtension` fields must not be `null` (at evaluation time) but may be
200218
either `static` or non-static.
201219

@@ -304,11 +322,23 @@ support for `TestInfo`, `TestReporter`, etc.).
304322
[[extensions-registration-inheritance]]
305323
==== Extension Inheritance
306324

307-
Registered extensions are inherited within test class hierarchies with top-down
308-
semantics. Similarly, extensions registered at the class-level are inherited at the
309-
method-level. Furthermore, a specific extension implementation can only be registered
310-
once for a given extension context and its parent contexts. Consequently, any attempt to
311-
register a duplicate extension implementation will be ignored.
325+
Registered extensions are inherited within test class hierarchies with top-down semantics.
326+
Similarly, extensions registered at the class-level are inherited at the method-level.
327+
This applies to all extensions, independent of how they are registered (declaratively or
328+
programmatically).
329+
330+
This means that extensions registered declaratively via `@ExtendWith` on a superclass will
331+
be registered before extensions registered declaratively via `@ExtendWith` on a subclass.
332+
333+
Similarly, extensions registered programmatically via `@RegisterExtension` or
334+
`@ExtendWith` on fields in a superclass will be registered before extensions registered
335+
programmatically via `@RegisterExtension` or `@ExtendWith` on fields in a subclass, unless
336+
`@Order` is used to alter that behavior (see <<extensions-registration-programmatic-order,
337+
Extension Registration Order>> for details).
338+
339+
NOTE: A specific extension implementation can only be registered once for a given
340+
extension context and its parent contexts. Consequently, any attempt to register a
341+
duplicate extension implementation will be ignored.
312342

313343
[[extensions-conditions]]
314344
=== Conditional Test Execution
@@ -704,6 +734,8 @@ and fields in a class or interface. Some of these methods search on implemented
704734
interfaces and within class hierarchies to find annotations. Consult the Javadoc for
705735
`{AnnotationSupport}` for further details.
706736

737+
NOTE: See also: <<extensions-supported-utilities-search-semantics>>
738+
707739
[[extensions-supported-utilities-classes]]
708740
==== Class Support
709741

@@ -720,6 +752,8 @@ class, and to find and invoke methods. Some of these methods traverse class hier
720752
to locate matching methods. Consult the Javadoc for `{ReflectionSupport}` for further
721753
details.
722754

755+
NOTE: See also: <<extensions-supported-utilities-search-semantics>>
756+
723757
[[extensions-supported-utilities-modifier]]
724758
==== Modifier Support
725759

@@ -737,6 +771,37 @@ wrapper types, date and time types from the `java.time package`, and some additi
737771
common Java types such as `File`, `BigDecimal`, `BigInteger`, `Currency`, `Locale`, `URI`,
738772
`URL`, `UUID`, etc. Consult the Javadoc for `{ConversionSupport}` for further details.
739773

774+
[[extensions-supported-utilities-search-semantics]]
775+
==== Field and Method Search Semantics
776+
777+
Various methods in `AnnotationSupport` and `ReflectionSupport` use search algorithms that
778+
traverse type hierarchies to locate matching fields and methods – for example,
779+
`AnnotationSupport.findAnnotatedFields(...)`, `ReflectionSupport.findMethods(...)`, etc.
780+
781+
As of JUnit 5.11 (JUnit Platform 1.11), field and method search algorithms adhere to
782+
standard Java semantics regarding whether a given field or method is visible or overridden
783+
according to the rules of the Java language.
784+
785+
Prior to JUnit 5.11, the field and method search algorithms applied what we now refer to
786+
as "legacy semantics". Legacy semantics consider fields and methods to be _hidden_,
787+
_shadowed_, or _superseded_ by fields and methods in super types (superclasses or
788+
interfaces) based solely on the field's name or the method's signature, disregarding the
789+
actual Java language semantics for visibility and the rules that determine if one method
790+
overrides another method.
791+
792+
Although the JUnit team recommends the use of the standard search semantics, developers
793+
may optionally revert to the legacy semantics via the
794+
`junit.platform.reflection.search.useLegacySemantics` JVM system property.
795+
796+
For example, to enable legacy search semantics for fields and methods, you can start your
797+
JVM with the following system property.
798+
799+
`-Djunit.platform.reflection.search.useLegacySemantics=true`
800+
801+
NOTE: Due to the low-level nature of the feature, the
802+
`junit.platform.reflection.search.useLegacySemantics` flag can only be set via a JVM
803+
system property. It cannot be set via a <<running-tests-config-params, configuration
804+
parameter>>.
740805

741806
[[extensions-execution-order]]
742807
=== Relative Execution Order of User Code and Extensions
@@ -863,31 +928,27 @@ callbacks implemented by `Extension2`. `Extension1` is therefore said to _wrap_
863928
JUnit Jupiter also guarantees _wrapping_ behavior within class and interface hierarchies
864929
for user-supplied _lifecycle methods_ (see <<writing-tests-definitions>>).
865930

866-
* `@BeforeAll` methods are inherited from superclasses as long as they are not _hidden_,
867-
_overridden_, or _superseded_ (i.e., replaced based on signature only, irrespective of
868-
Java's visibility rules). Furthermore, `@BeforeAll` methods from superclasses will be
869-
executed **before** `@BeforeAll` methods in subclasses.
931+
* `@BeforeAll` methods are inherited from superclasses as long as they are not
932+
_overridden_. Furthermore, `@BeforeAll` methods from superclasses will be executed
933+
**before** `@BeforeAll` methods in subclasses.
870934
** Similarly, `@BeforeAll` methods declared in an interface are inherited as long as they
871-
are not _hidden_ or _overridden_, and `@BeforeAll` methods from an interface will be
872-
executed **before** `@BeforeAll` methods in the class that implements the interface.
873-
* `@AfterAll` methods are inherited from superclasses as long as they are not _hidden_,
874-
_overridden_, or _superseded_ (i.e., replaced based on signature only, irrespective of
875-
Java's visibility rules). Furthermore, `@AfterAll` methods from superclasses will be
876-
executed **after** `@AfterAll` methods in subclasses.
935+
are not _overridden_, and `@BeforeAll` methods from an interface will be executed
936+
**before** `@BeforeAll` methods in the class that implements the interface.
937+
* `@AfterAll` methods are inherited from superclasses as long as they are not
938+
_overridden_. Furthermore, `@AfterAll` methods from superclasses will be executed
939+
**after** `@AfterAll` methods in subclasses.
877940
** Similarly, `@AfterAll` methods declared in an interface are inherited as long as they
878-
are not _hidden_ or _overridden_, and `@AfterAll` methods from an interface will be
879-
executed **after** `@AfterAll` methods in the class that implements the interface.
941+
are not _overridden_, and `@AfterAll` methods from an interface will be executed
942+
**after** `@AfterAll` methods in the class that implements the interface.
880943
* `@BeforeEach` methods are inherited from superclasses as long as they are not
881-
_overridden_ or _superseded_ (i.e., replaced based on signature only, irrespective of
882-
Java's visibility rules). Furthermore, `@BeforeEach` methods from superclasses will be
883-
executed **before** `@BeforeEach` methods in subclasses.
944+
_overridden_. Furthermore, `@BeforeEach` methods from superclasses will be executed
945+
**before** `@BeforeEach` methods in subclasses.
884946
** Similarly, `@BeforeEach` methods declared as interface default methods are inherited as
885947
long as they are not _overridden_, and `@BeforeEach` default methods will be executed
886948
**before** `@BeforeEach` methods in the class that implements the interface.
887949
* `@AfterEach` methods are inherited from superclasses as long as they are not
888-
_overridden_ or _superseded_ (i.e., replaced based on signature only, irrespective of
889-
Java's visibility rules). Furthermore, `@AfterEach` methods from superclasses will be
890-
executed **after** `@AfterEach` methods in subclasses.
950+
_overridden_. Furthermore, `@AfterEach` methods from superclasses will be executed
951+
**after** `@AfterEach` methods in subclasses.
891952
** Similarly, `@AfterEach` methods declared as interface default methods are inherited as
892953
long as they are not _overridden_, and `@AfterEach` default methods will be executed
893954
**after** `@AfterEach` methods in the class that implements the interface.

0 commit comments

Comments
 (0)