diff --git a/src/main/java/net/hostsharing/hsadminng/reflection/AnnotationFinder.java b/src/main/java/net/hostsharing/hsadminng/reflection/AnnotationFinder.java new file mode 100644 index 00000000..705e8326 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/reflection/AnnotationFinder.java @@ -0,0 +1,47 @@ +package net.hostsharing.hsadminng.reflection; + +import lombok.experimental.UtilityClass; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Optional; + +import static java.util.Optional.empty; + +@UtilityClass +public class AnnotationFinder { + + public static Optional findCallerAnnotation( + final Class annotationClassToFind, + final Class annotationClassToStopLookup + ) { + for (var element : Thread.currentThread().getStackTrace()) { + try { + final var clazz = Class.forName(element.getClassName()); + final var method = getMethodFromStackElement(clazz, element); + + // Check if the method is annotated with the desired annotation + if (method != null) { + if (method.isAnnotationPresent(annotationClassToFind)) { + return Optional.of(method.getAnnotation(annotationClassToFind)); + } else if (method.isAnnotationPresent(annotationClassToStopLookup)) { + return empty(); + } + } + } catch (final ClassNotFoundException | NoSuchMethodException e) { + throw new RuntimeException(e); // FIXME: when does this happen? + } + } + return empty(); + } + + private static Method getMethodFromStackElement(Class clazz, StackTraceElement element) + throws NoSuchMethodException { + for (var method : clazz.getDeclaredMethods()) { + if (method.getName().equals(element.getMethodName())) { + return method; + } + } + return null; + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/HsOfficeUseCasesTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/HsOfficeUseCasesTest.java index 9e4fb3e0..69857d7c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/HsOfficeUseCasesTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/HsOfficeUseCasesTest.java @@ -30,7 +30,7 @@ class HsOfficeUseCasesTest extends UseCaseTest { @Order(1010) @Produces(explicitly = "Partner: Test AG", implicitly = "Person: Test AG") void shouldCreatePartner() { - new CreatePartner(this, "Partner: Test AG") + new CreatePartner(this) .given("partnerNumber", 31010) .given("personType", "LEGAL_PERSON") .given("tradeName", "Test AG") @@ -73,7 +73,7 @@ class HsOfficeUseCasesTest extends UseCaseTest { @Requires("Person: Test AG") @Produces("Debitor: Billing GmbH") void shouldCreateExternalDebitorForPartner() { - new CreateExternalDebitorForPartner(this, "Debitor: Billing GmbH") + new CreateExternalDebitorForPartner(this) .given("partnerPersonUuid", "%{Person: Test AG}") .given("billingContactCaption", "Billing GmbH - billing department") .given("billingContactEmailAddress", "billing@test-ag.example.org") @@ -103,7 +103,7 @@ class HsOfficeUseCasesTest extends UseCaseTest { @Requires("Debitor: Test AG - main debitor") @Produces("SEPA-Mandate: Test AG") void shouldCreateSepaMandateForDebitor() { - new CreateSepaMandataForDebitor(this, "SEPA-Mandate: Test AG") + new CreateSepaMandataForDebitor(this) .given("debitor", "Test AG") .given("memberNumberSuffix", "00") .given("validFrom", "2024-10-15") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCase.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCase.java index 5fec03ba..1228d7e6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCase.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCase.java @@ -4,7 +4,11 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import io.restassured.response.Response; import io.restassured.response.ValidatableResponse; +import net.hostsharing.hsadminng.reflection.AnnotationFinder; import org.apache.commons.collections4.map.LinkedMap; +import org.hibernate.AssertionFailure; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -16,6 +20,8 @@ import java.util.function.Supplier; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.startsWith; +import static org.junit.platform.commons.util.StringUtils.isBlank; +import static org.junit.platform.commons.util.StringUtils.isNotBlank; public abstract class UseCase> { @@ -26,7 +32,7 @@ public abstract class UseCase> { private String nextTitle; // FIXME: ugly public UseCase(final UseCaseTest testSuite) { - this(testSuite, null); + this(testSuite, getResultAliasFromProducesAnnotationInCallStack()); } public UseCase(final UseCaseTest testSuite, final String resultAlias) { @@ -189,4 +195,19 @@ public abstract class UseCase> { //noinspection unchecked return (T) this; } + + private static @Nullable String getResultAliasFromProducesAnnotationInCallStack() { + return AnnotationFinder.findCallerAnnotation(Produces.class, Test.class) + .map(produces -> oneOf(produces.value(), produces.explicitly())) + .orElse(null); + } + + private static String oneOf(final String one, final String another) { + if (isNotBlank(one) && isBlank(another)) { + return one; + } else if ( isBlank(one) && isNotBlank(another)) { + return another; + } + throw new AssertionFailure("exactly one value required, but got '" + one + "' and '" + another + "'"); + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCaseTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCaseTest.java index 2130780c..4ad99cdf 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCaseTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/UseCaseTest.java @@ -8,7 +8,6 @@ import net.hostsharing.hsadminng.lambda.Reducer; import net.hostsharing.hsadminng.rbac.context.ContextBasedTest; import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import org.apache.commons.collections4.SetUtils; -import org.hibernate.AssertionFailure; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; @@ -148,15 +147,6 @@ public abstract class UseCaseTest extends ContextBasedTest { return all; } - private String oneOf(final String one, final String another) { - if (one != null && another == null) { - return one; - } else if (one == null && another != null) { - return another; - } - throw new AssertionFailure("excactly one value required"); - } - static boolean containsAlias(final String alias) { return aliases.containsKey(alias); } @@ -177,10 +167,6 @@ public abstract class UseCaseTest extends ContextBasedTest { properties.put(name, (value instanceof String string) ? resolve(string) : value); } - static LinkedHashMap properties() { - return new LinkedHashMap<>(properties); - } - static Map knowVariables() { final var map = new LinkedHashMap(); UseCaseTest.aliases.forEach((key, value) -> map.put(key, value.uuid())); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateExternalDebitorForPartner.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateExternalDebitorForPartner.java index bc446871..9d902dcc 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateExternalDebitorForPartner.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateExternalDebitorForPartner.java @@ -9,8 +9,8 @@ import static org.springframework.http.HttpStatus.CREATED; public class CreateExternalDebitorForPartner extends UseCase { - public CreateExternalDebitorForPartner(final UseCaseTest testSuite, final String resultAlias) { - super(testSuite, resultAlias); + public CreateExternalDebitorForPartner(final UseCaseTest testSuite) { + super(testSuite); requires("Person: Billing GmbH", alias -> new CreatePerson(testSuite, alias) .given("personType", "LEGAL_PERSON") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateSepaMandataForDebitor.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateSepaMandataForDebitor.java index ee233cdb..33f27d4c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateSepaMandataForDebitor.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/debitor/CreateSepaMandataForDebitor.java @@ -8,8 +8,8 @@ import static org.springframework.http.HttpStatus.CREATED; public class CreateSepaMandataForDebitor extends UseCase { - public CreateSepaMandataForDebitor(final UseCaseTest testSuite, final String resultAlias) { - super(testSuite, resultAlias); + public CreateSepaMandataForDebitor(final UseCaseTest testSuite) { + super(testSuite); } @Override diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/partner/CreatePartner.java b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/partner/CreatePartner.java index bf7a19f6..d4dcf0e6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/partner/CreatePartner.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/usecases/partner/CreatePartner.java @@ -11,6 +11,10 @@ public class CreatePartner extends UseCase { super(testSuite, resultAlias); } + public CreatePartner(final UseCaseTest testSuite) { + super(testSuite); + } + @Override protected HttpResponse run() {