Skip to content

Issues/2914 private lifecycle methods should cause exception #2951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@
* <h2>Inheritance and Execution Order</h2>
*
* <p>{@code @AfterAll} methods are inherited from superclasses as long as
* they are not <em>hidden</em> or <em>overridden</em>. Furthermore,
* {@code @AfterAll} methods from superclasses will be executed after
* they are not <em>hidden</em> (default mode with {@code static} modifier), or
* <em>overridden</em>, or <em>superseded</em> (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.
*
* <p>Similarly, {@code @AfterAll} methods declared in an interface are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
* <h2>Inheritance and Execution Order</h2>
*
* <p>{@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 <em>superseded</em> (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.
*
* <p>Similarly, {@code @AfterEach} methods declared as <em>interface default
* methods</em> are inherited as long as they are not overridden, and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
* <h2>Inheritance and Execution Order</h2>
*
* <p>{@code @BeforeAll} methods are inherited from superclasses as long as
* they are not <em>hidden</em> or <em>overridden</em>. Furthermore,
* they are not <em>hidden</em> (default mode with {@code static} modifier), or
* <em>overridden</em>, or <em>superseded</em> (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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
* <h2>Inheritance and Execution Order</h2>
*
* <p>{@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 <em>superseded</em> (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.
*
* <p>Similarly, {@code @BeforeEach} methods declared as <em>interface default
* methods</em> are inherited as long as they are not overridden, and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,21 @@ private LifecycleMethodUtils() {
}

static List<Method> findBeforeAllMethods(Class<?> testClass, boolean requireStatic) {
return findMethodsAndAssertStatic(testClass, requireStatic, BeforeAll.class, HierarchyTraversalMode.TOP_DOWN);
return findMethodsAndAssertStaticAndNonPrivate(testClass, requireStatic, BeforeAll.class,
HierarchyTraversalMode.TOP_DOWN);
}

static List<Method> findAfterAllMethods(Class<?> testClass, boolean requireStatic) {
return findMethodsAndAssertStatic(testClass, requireStatic, AfterAll.class, HierarchyTraversalMode.BOTTOM_UP);
return findMethodsAndAssertStaticAndNonPrivate(testClass, requireStatic, AfterAll.class,
HierarchyTraversalMode.BOTTOM_UP);
}

static List<Method> findBeforeEachMethods(Class<?> testClass) {
return findMethodsAndAssertNonStatic(testClass, BeforeEach.class, HierarchyTraversalMode.TOP_DOWN);
return findMethodsAndAssertNonStaticAndNonPrivate(testClass, BeforeEach.class, HierarchyTraversalMode.TOP_DOWN);
}

static List<Method> findAfterEachMethods(Class<?> testClass) {
return findMethodsAndAssertNonStatic(testClass, AfterEach.class, HierarchyTraversalMode.BOTTOM_UP);
return findMethodsAndAssertNonStaticAndNonPrivate(testClass, AfterEach.class, HierarchyTraversalMode.BOTTOM_UP);
}

private static void assertStatic(Class<? extends Annotation> annotationType, Method method) {
Expand All @@ -67,26 +69,39 @@ private static void assertNonStatic(Class<? extends Annotation> annotationType,
}
}

private static void assertNonPrivate(Class<? extends Annotation> annotationType, Method method) {
if (ReflectionUtils.isPrivate(method)) {
throw new JUnitException(String.format("@%s method '%s' must not be private.",
annotationType.getSimpleName(), method.toGenericString()));
}
}

private static void assertVoid(Class<? extends Annotation> annotationType, Method method) {
if (!returnsVoid(method)) {
throw new JUnitException(String.format("@%s method '%s' must not return a value.",
annotationType.getSimpleName(), method.toGenericString()));
}
}

private static List<Method> findMethodsAndAssertStatic(Class<?> testClass, boolean requireStatic,
private static List<Method> findMethodsAndAssertStaticAndNonPrivate(Class<?> testClass, boolean requireStatic,
Class<? extends Annotation> annotationType, HierarchyTraversalMode traversalMode) {
List<Method> methods = findMethodsAndCheckVoidReturnType(testClass, annotationType, traversalMode);
if (requireStatic) {
methods.forEach(method -> assertStatic(annotationType, method));
}
methods.forEach(method -> assertNonPrivate(annotationType, method));

return methods;
}

private static List<Method> findMethodsAndAssertNonStatic(Class<?> testClass,
private static List<Method> findMethodsAndAssertNonStaticAndNonPrivate(Class<?> testClass,
Class<? extends Annotation> annotationType, HierarchyTraversalMode traversalMode) {
List<Method> methods = findMethodsAndCheckVoidReturnType(testClass, annotationType, traversalMode);
methods.forEach(method -> assertNonStatic(annotationType, method));
methods.forEach(method -> {
assertNonStatic(annotationType, method);
assertNonPrivate(annotationType, method);
});

return methods;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.junit.platform.testkit.engine.Events;

/**
* Integration tests that very proper handling of invalid configuration for
* Integration tests that verify proper handling of invalid configuration for
* lifecycle methods in conjunction with the {@link JupiterTestEngine}.
*
* <p>In general, configuration errors should not be thrown until the
Expand All @@ -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) {
Expand Down Expand Up @@ -80,7 +100,7 @@ void test() {
}
}

static class TestCaseWithInvalidBeforeAllMethod {
static class TestCaseWithInvalidNonStaticBeforeAllMethod {

// must be static
@BeforeAll
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -128,4 +184,16 @@ void test() {
}
}

static class TestCaseWithInvalidPrivateAfterEachMethod {

// must NOT be private
@AfterEach
private void afterEach() {
}

@Test
void test() {
}
}

}
Loading