diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterAll.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterAll.java index d4059380111f..a5ab2e1abc4d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterAll.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterAll.java @@ -43,8 +43,10 @@ *
{@code @AfterAll} methods are inherited from superclasses as long as - * they are not hidden or overridden. Furthermore, - * {@code @AfterAll} methods from superclasses will be executed after + * they are not hidden (default mode with {@code static} modifier), or + * overridden, or superseded (i.e., replaced based on + * signature only, irrespective of Java's visibility rules). Furthermore, + * {@code @AfterAll} methods from superclasses will be executed before * {@code @AfterAll} methods in subclasses. * *
Similarly, {@code @AfterAll} methods declared in an interface are diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterEach.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterEach.java index 3595b3fab594..c6340076e0f2 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterEach.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AfterEach.java @@ -36,8 +36,10 @@ *
{@code @AfterEach} methods are inherited from superclasses as long as - * they are not overridden. Furthermore, {@code @AfterEach} methods from - * superclasses will be executed after {@code @AfterEach} methods in subclasses. + * they are not overridden or superseded (i.e., replaced based on + * signature only, irrespective of Java's visibility rules). Furthermore, + * {@code @AfterEach} methods from superclasses will be executed after + * {@code @AfterEach} methods in subclasses. * *
Similarly, {@code @AfterEach} methods declared as interface default * methods are inherited as long as they are not overridden, and diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeAll.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeAll.java index 5023334c614e..5c85c196d262 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeAll.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeAll.java @@ -43,7 +43,9 @@ *
{@code @BeforeAll} methods are inherited from superclasses as long as - * they are not hidden or overridden. Furthermore, + * they are not hidden (default mode with {@code static} modifier), or + * overridden, or superseded (i.e., replaced based on + * signature only, irrespective of Java's visibility rules). Furthermore, * {@code @BeforeAll} methods from superclasses will be executed before * {@code @BeforeAll} methods in subclasses. * diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeEach.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeEach.java index eb8fa9aaf20e..b6247315b40f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeEach.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/BeforeEach.java @@ -36,8 +36,10 @@ *
{@code @BeforeEach} methods are inherited from superclasses as long as - * they are not overridden. Furthermore, {@code @BeforeEach} methods from - * superclasses will be executed before {@code @BeforeEach} methods in subclasses. + * they are not overridden or superseded (i.e., replaced based on + * signature only, irrespective of Java's visibility rules). Furthermore, + * {@code @BeforeEach} methods from superclasses will be executed before + * {@code @BeforeEach} methods in subclasses. * *
Similarly, {@code @BeforeEach} methods declared as interface default
* methods are inherited as long as they are not overridden, and
diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java
index 53a2a5c5360a..9b9a43a73a20 100644
--- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java
+++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java
@@ -37,19 +37,21 @@ private LifecycleMethodUtils() {
}
static List In general, configuration errors should not be thrown until the
@@ -34,23 +34,43 @@
class InvalidLifecycleMethodConfigurationTests extends AbstractJupiterTestEngineTests {
@Test
- void executeValidTestCaseAlongsideTestCaseWithInvalidBeforeAllDeclaration() {
- assertExecutionResults(TestCaseWithInvalidBeforeAllMethod.class);
+ void executeValidTestCaseAlongsideTestCaseWithInvalidNonStaticBeforeAllDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidNonStaticBeforeAllMethod.class);
}
@Test
- void executeValidTestCaseAlongsideTestCaseWithInvalidAfterAllDeclaration() {
- assertExecutionResults(TestCaseWithInvalidAfterAllMethod.class);
+ void executeValidTestCaseAlongsideTestCaseWithInvalidPrivateBeforeAllDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidPrivateBeforeAllMethod.class);
}
@Test
- void executeValidTestCaseAlongsideTestCaseWithInvalidBeforeEachDeclaration() {
- assertExecutionResults(TestCaseWithInvalidBeforeEachMethod.class);
+ void executeValidTestCaseAlongsideTestCaseWithInvalidNonStaticAfterAllDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidNonStaticAfterAllMethod.class);
}
@Test
- void executeValidTestCaseAlongsideTestCaseWithInvalidAfterEachDeclaration() {
- assertExecutionResults(TestCaseWithInvalidAfterEachMethod.class);
+ void executeValidTestCaseAlongsideTestCaseWithInvalidPrivateAfterAllDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidPrivateAfterAllMethod.class);
+ }
+
+ @Test
+ void executeValidTestCaseAlongsideTestCaseWithInvalidStaticBeforeEachDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidStaticBeforeEachMethod.class);
+ }
+
+ @Test
+ void executeValidTestCaseAlongsideTestCaseWithInvalidPrivateBeforeEachDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidPrivateBeforeEachMethod.class);
+ }
+
+ @Test
+ void executeValidTestCaseAlongsideTestCaseWithInvalidStaticAfterEachDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidStaticAfterEachMethod.class);
+ }
+
+ @Test
+ void executeValidTestCaseAlongsideTestCaseWithInvalidPrivateAfterEachDeclaration() {
+ assertExecutionResults(TestCaseWithInvalidPrivateAfterEachMethod.class);
}
private void assertExecutionResults(Class> invalidTestClass) {
@@ -80,7 +100,7 @@ void test() {
}
}
- static class TestCaseWithInvalidBeforeAllMethod {
+ static class TestCaseWithInvalidNonStaticBeforeAllMethod {
// must be static
@BeforeAll
@@ -92,7 +112,19 @@ void test() {
}
}
- static class TestCaseWithInvalidAfterAllMethod {
+ static class TestCaseWithInvalidPrivateBeforeAllMethod {
+
+ // must not be private
+ @BeforeAll
+ private static void beforeAll() {
+ }
+
+ @Test
+ void test() {
+ }
+ }
+
+ static class TestCaseWithInvalidNonStaticAfterAllMethod {
// must be static
@AfterAll
@@ -104,7 +136,19 @@ void test() {
}
}
- static class TestCaseWithInvalidBeforeEachMethod {
+ static class TestCaseWithInvalidPrivateAfterAllMethod {
+
+ // must not be private
+ @AfterAll
+ private static void afterAll() {
+ }
+
+ @Test
+ void test() {
+ }
+ }
+
+ static class TestCaseWithInvalidStaticBeforeEachMethod {
// must NOT be static
@BeforeEach
@@ -116,7 +160,19 @@ void test() {
}
}
- static class TestCaseWithInvalidAfterEachMethod {
+ static class TestCaseWithInvalidPrivateBeforeEachMethod {
+
+ // must NOT be private
+ @BeforeEach
+ private void beforeEach() {
+ }
+
+ @Test
+ void test() {
+ }
+ }
+
+ static class TestCaseWithInvalidStaticAfterEachMethod {
// must NOT be static
@AfterEach
@@ -128,4 +184,16 @@ void test() {
}
}
+ static class TestCaseWithInvalidPrivateAfterEachMethod {
+
+ // must NOT be private
+ @AfterEach
+ private void afterEach() {
+ }
+
+ @Test
+ void test() {
+ }
+ }
+
}
diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/LifecycleMethodSupersedingTests.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/LifecycleMethodSupersedingTests.java
new file mode 100644
index 000000000000..cfc92c17974d
--- /dev/null
+++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/LifecycleMethodSupersedingTests.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2015-2022 the original author or authors.
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v2.0 which
+ * accompanies this distribution and is available at
+ *
+ * https://www.eclipse.org/legal/epl-v20.html
+ */
+
+package org.junit.jupiter.engine;
+
+/*
+ * Copyright 2015-2022 the original author or authors.
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v2.0 which
+ * accompanies this distribution and is available at
+ *
+ * https://www.eclipse.org/legal/epl-v20.html
+ */
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Integration tests that explicitly demonstrate the shadowing/overriding
+ * rules for lifecycle methods in the {@link JupiterTestEngine}.
+ *
+ * @since 5.9
+ */
+class LifecycleMethodSupersedingTests {
+
+ @Nested
+ @DisplayName("A package-private lifecycle super-method can be superseded by")
+ class PackagePrivateSuperClassTests {
+
+ @Nested
+ @DisplayName("a protected lifecycle method in the derived class")
+ class ProtectedExtendsPackagePrivateLifecycleMethod
+ extends SuperClassWithPackagePrivateLifecycleMethodTestCase {
+
+ @BeforeEach
+ protected void beforeEach() {
+ }
+
+ }
+
+ @Nested
+ @DisplayName("a package-private lifecycle method in the derived class")
+ class PackagePrivateExtendsPackagePrivateLifecycleMethod
+ extends SuperClassWithPackagePrivateLifecycleMethodTestCase {
+
+ @BeforeEach
+ void beforeEach() {
+ }
+
+ }
+
+ @Nested
+ @DisplayName("a public lifecycle method in the derived class")
+ class PublicExtendsPackagePrivateLifecycleMethod extends SuperClassWithPackagePrivateLifecycleMethodTestCase {
+
+ @BeforeEach
+ public void beforeEach() {
+ }
+
+ }
+ }
+
+ @Nested
+ @DisplayName("A protected lifecycle super-method can be superseded by")
+ class ProtectedSuperClassTests {
+
+ @Nested
+ @DisplayName("a protected lifecycle method in the derived class")
+ class ProtectedExtendsPackagePrivate extends SuperClassWithProtectedLifecycleMethodTestCase {
+
+ @BeforeEach
+ protected void beforeEach() {
+ }
+
+ }
+
+ @Nested
+ @DisplayName("a public lifecycle method in the derived class")
+ class PublicExtendsPackagePrivate extends SuperClassWithProtectedLifecycleMethodTestCase {
+
+ @BeforeEach
+ public void beforeEach() {
+ }
+
+ }
+ }
+
+ @Nested
+ @DisplayName("A public lifecycle super-method can be superseded by")
+ class PublicSuperClassTests {
+
+ @Nested
+ @DisplayName("a public lifecycle method in the derived class")
+ class PublicExtendsPackagePrivate extends SuperClassWithPublicLifecycleMethodTestCase {
+
+ @BeforeEach
+ public void beforeEach() {
+ }
+
+ }
+ }
+
+}
+
+// -------------------------------------------------------------------------
+
+class SuperClassWithPackagePrivateLifecycleMethodTestCase {
+
+ @BeforeEach
+ void beforeEach() {
+ fail();
+ }
+
+ @Test
+ void test() {
+ }
+
+}
+
+class SuperClassWithProtectedLifecycleMethodTestCase {
+
+ @BeforeEach
+ protected void beforeEach() {
+ fail();
+ }
+
+ @Test
+ void test() {
+ }
+
+}
+
+class SuperClassWithPublicLifecycleMethodTestCase {
+
+ @BeforeEach
+ public void beforeEach() {
+ fail();
+ }
+
+ @Test
+ void test() {
+ }
+
+}