From 89747bd188eaa7835db7409754e4c6ec752418cd Mon Sep 17 00:00:00 2001 From: Manfred Hanke Date: Sat, 7 May 2022 01:19:58 +0200 Subject: [PATCH] JUnit5-support for libraries with `@ArchTest`s in abstract base classes This corresponds to 59f8c4da95fb95a4be49e9aad2311b3af06edd26, which added the same feature for JUnit4 (Issue: #104). Signed-off-by: Manfred Hanke --- .../internal/ArchUnitTestDescriptor.java | 16 ++++++++------ .../internal/ArchUnitTestEngineTest.java | 21 +++++++++++++++++++ ...hTestWithLibraryWithAbstractBaseClass.java | 15 +++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/testexamples/abstractbase/ArchTestWithLibraryWithAbstractBaseClass.java diff --git a/archunit-junit/junit5/engine/src/main/java/com/tngtech/archunit/junit/internal/ArchUnitTestDescriptor.java b/archunit-junit/junit5/engine/src/main/java/com/tngtech/archunit/junit/internal/ArchUnitTestDescriptor.java index e359edecb8..3100af300e 100644 --- a/archunit-junit/junit5/engine/src/main/java/com/tngtech/archunit/junit/internal/ArchUnitTestDescriptor.java +++ b/archunit-junit/junit5/engine/src/main/java/com/tngtech/archunit/junit/internal/ArchUnitTestDescriptor.java @@ -109,13 +109,19 @@ private static void resolveChildren( if (ArchTests.class.isAssignableFrom(field.getType())) { resolveArchRules(parent, resolver, field, classes); } else { - Class fieldOwner = parent instanceof ArchUnitTestDescriptor - ? ((ArchUnitTestDescriptor) parent).testClass - : field.getDeclaringClass(); + Class fieldOwner = tryToFindOwner(parent).orElseGet(field::getDeclaringClass); parent.addChild(new ArchUnitRuleDescriptor(resolver.getUniqueId(), getValue(field, fieldOwner), classes, field)); } } + private static Optional> tryToFindOwner(TestDescriptor parent) { + return parent instanceof ArchUnitTestDescriptor + ? Optional.of(((ArchUnitTestDescriptor) parent).testClass) + : parent instanceof ArchUnitArchTestsDescriptor + ? Optional.of(((ArchUnitArchTestsDescriptor) parent).archTests.getDefinitionLocation()) + : Optional.empty(); + } + private static T getValue(Field field, Class fieldOwner) { return getValueOrThrowException(field, fieldOwner, ArchTestInitializationException::new); } @@ -198,9 +204,7 @@ public Type getType() { @Override public ArchUnitEngineExecutionContext execute(ArchUnitEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { - Class methodOwner = getParent().flatMap(parent -> - parent instanceof ArchUnitTestDescriptor ? Optional.of(((ArchUnitTestDescriptor) parent).testClass) : Optional.>empty() - ).orElseGet(method::getDeclaringClass); + Class methodOwner = getParent().flatMap(ArchUnitTestDescriptor::tryToFindOwner).orElseGet(method::getDeclaringClass); invokeMethod(method, methodOwner, classes.get()); return context; } diff --git a/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/ArchUnitTestEngineTest.java b/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/ArchUnitTestEngineTest.java index 55bba0b11a..b616d86ac9 100644 --- a/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/ArchUnitTestEngineTest.java +++ b/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/ArchUnitTestEngineTest.java @@ -38,6 +38,7 @@ import com.tngtech.archunit.junit.internal.testexamples.UnwantedClass; import com.tngtech.archunit.junit.internal.testexamples.abstractbase.ArchTestWithAbstractBaseClassWithFieldRule; import com.tngtech.archunit.junit.internal.testexamples.abstractbase.ArchTestWithAbstractBaseClassWithMethodRule; +import com.tngtech.archunit.junit.internal.testexamples.abstractbase.ArchTestWithLibraryWithAbstractBaseClass; import com.tngtech.archunit.junit.internal.testexamples.ignores.IgnoredClass; import com.tngtech.archunit.junit.internal.testexamples.ignores.IgnoredField; import com.tngtech.archunit.junit.internal.testexamples.ignores.IgnoredLibrary; @@ -872,6 +873,26 @@ void private_instance_libraries() { testListener.verifyViolation(testId, UnwantedClass.CLASS_VIOLATING_RULES.getSimpleName())); } + @Test + public void library_with_rules_in_abstract_base_class() { + simulateCachedClassesForTest(ArchTestWithLibraryWithAbstractBaseClass.class, UnwantedClass.CLASS_SATISFYING_RULES); + + EngineExecutionTestListener testListener = execute(engineId, ArchTestWithLibraryWithAbstractBaseClass.class); + + testListener.verifySuccessful(engineId + .append(CLASS_SEGMENT_TYPE, ArchTestWithLibraryWithAbstractBaseClass.class.getName()) + .append(FIELD_SEGMENT_TYPE, ArchTestWithLibraryWithAbstractBaseClass.FIELD_RULE_LIBRARY_NAME) + .append(CLASS_SEGMENT_TYPE, ArchTestWithAbstractBaseClassWithFieldRule.class.getName()) + .append(FIELD_SEGMENT_TYPE, ArchTestWithAbstractBaseClassWithFieldRule.INSTANCE_FIELD_NAME) + ); + testListener.verifySuccessful(engineId + .append(CLASS_SEGMENT_TYPE, ArchTestWithLibraryWithAbstractBaseClass.class.getName()) + .append(FIELD_SEGMENT_TYPE, ArchTestWithLibraryWithAbstractBaseClass.METHOD_RULE_LIBRARY_NAME) + .append(CLASS_SEGMENT_TYPE, ArchTestWithAbstractBaseClassWithMethodRule.class.getName()) + .append(METHOD_SEGMENT_TYPE, ArchTestWithAbstractBaseClassWithMethodRule.INSTANCE_METHOD_NAME) + ); + } + @Test void rule_by_unique_id_without_violation() { UniqueId fieldRuleInLibrary = simpleRulesInLibraryId(engineId) diff --git a/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/testexamples/abstractbase/ArchTestWithLibraryWithAbstractBaseClass.java b/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/testexamples/abstractbase/ArchTestWithLibraryWithAbstractBaseClass.java new file mode 100644 index 0000000000..b24fddc8d5 --- /dev/null +++ b/archunit-junit/junit5/engine/src/test/java/com/tngtech/archunit/junit/internal/testexamples/abstractbase/ArchTestWithLibraryWithAbstractBaseClass.java @@ -0,0 +1,15 @@ +package com.tngtech.archunit.junit.internal.testexamples.abstractbase; + +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.junit.ArchTests; + +@AnalyzeClasses(packages = "some.dummy.package") +public class ArchTestWithLibraryWithAbstractBaseClass { + public static final String FIELD_RULE_LIBRARY_NAME = "fieldRules"; + public static final String METHOD_RULE_LIBRARY_NAME = "methodRules"; + @ArchTest + ArchTests fieldRules = ArchTests.in(ArchTestWithAbstractBaseClassWithFieldRule.class); + @ArchTest + ArchTests methodRules = ArchTests.in(ArchTestWithAbstractBaseClassWithMethodRule.class); +}