Repository: junit-team/junit5

Issue #3553: Align method and field search algorithms with Java semantics
Created: 2023-11-10T15:37:37Z
Overview
As discussed in #3532 (comment), the search algorithms in JUnit 5 that are used to locate methods and fields have historically had the following undesirable characteristic.
A field supersedes (shadows, hides, overrides) a field with the same name in a superclass unless a filter (Predicate) is applied that ignores one of the fields (such as a static check or a check for the presence of a specific annotation).
This also applies to any methods looked up via JUnit 5's reflection support -- for example, lifecycle methods and test methods in JUnit Jupiter.
The JUnit 5 team discussed this topic today and decided to revise our search algorithms to align with Java semantics regarding visibility and overriding.
Specifically, we want to ensure that our search algorithms do not treat something as overridden when it is not overridden according to the Java Virtual Machine Specification (JVMS).
As a consequence, several currently unsupported use cases would become supported -- for example:

Two @TempDir fields with the same name in a superclass and subclass would both be injected.
Two @BeforeEach methods with the same name/signature in a superclass and subclass would both be invoked, if the @BeforeEach method in the superclass is package-private and the subclass resides in a different package (i.e., the @BeforeEach method in the subclass does not @Override the @BeforeEach method in the superclass according to the JVMS).

External Resources

Java Virtual Machine Specification: § 5.4.5, Overriding

Related Issues

#960
#2390
#2626
#3242
#3498
#3532

Deliverables

 Align method and field search algorithms with Java semantics regarding visibility/overridability.
 Introduce tests for overridden method support. See comment below.
 Introduce a configuration parameter / system property -- for example, junit.platform.reflection.search.useLegacySemantics = true -- that allows a project to revert to the previous behavior.
 Document in User Guide.
 Document in Release Notes.

Duplicate issue #3498: `@BeforeAll` method in super class skipped when it has same name as a `@BeforeEach` method in subclass
Created: 2023-10-09T07:40:02Z
Steps to reproduce
Given:
package a;

import org.junit.jupiter.api.BeforeAll;

public abstract class A {

    @BeforeAll
    static void before() {
        System.out.println("A");
    }
}
and
package b;

import a.A;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class B extends A {

    @BeforeEach
    void before() {
        System.out.println("B");
    }

    @Test
    void test() {
        System.out.println("Hi there");
    }
}
Executing the test in B prints: B and Hi there.  Note the absence of  A: the @BeforeAll method was not called.  Note that the non-static before method in B does not override the static method (it is in a different package), nor does it conflict with it.  Renaming the before method in B or A fixes the problem.
This can easily happen when you have an abstract base class in some utility package, and you are extending it to build tests.  If you happen to name a method in this test class that conflicts with a package-private method in the base class, things do not work as expected.
Workaround:
Ensure the names in the base class are sufficiently unique that they're unlikely to have similar names in a subclass.
Deliverables

A fix for this problem.  It probably is a problem with annotation scanning not being thorough enough and not taking this special case into account.

Closing comment (2023-11-10T15:46:27Z): Closely related to:

#3553