fix requires with resolvable alias name

This commit is contained in:
Michael Hoennig 2024-11-29 13:27:23 +01:00
parent 87e23b9355
commit 0ae0131ef7
5 changed files with 61 additions and 40 deletions

View File

@ -444,7 +444,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test
@Order(4301)
@Requires("Membership: M-3101000 - Test AG")
@Produces("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction")
@Produces("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
void shouldSubscribeCoopAssets() {
new CreateCoopAssetsDepositTransaction(scenarioTest)
.given("memberNumber", "M-3101000")
@ -468,8 +468,8 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test
@Order(4303)
@Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction")
@Produces("Coop-Assets M-3101000 - Test AG - DISBURSAL Transaction")
@Requires("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
@Produces("Coop-Assets: M-3101000 - Test AG - DISBURSAL Transaction")
void shouldDisburseCoopAssets() {
new CreateCoopAssetsDisbursalTransaction(scenarioTest)
.given("memberNumber", "M-3101000")
@ -482,8 +482,8 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test
@Order(4304)
@Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction")
@Produces(explicitly = "Coop-Assets M-3101000 - Test AG - TRANSFER Transaction", implicitly = "Membership M-4303000 - New AG")
@Requires("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
@Produces(explicitly = "Coop-Assets: M-3101000 - Test AG - TRANSFER Transaction", implicitly = "Membership: M-4303000 - New AG")
void shouldTransferCoopAssets() {
new CreateCoopAssetsTransferTransaction(scenarioTest)
.given("transferringMemberNumber", "M-3101000")
@ -497,7 +497,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test
@Order(4305)
@Requires("Coop-Assets M-3101000 - Test AG - TRANSFER Transaction")
@Requires("Coop-Assets: M-3101000 - Test AG - TRANSFER Transaction")
void shouldRevertCoopAssetsTransferIncludingRelatedAssetAdoption() {
new CreateCoopAssetsRevertTransferTransaction(scenarioTest)
.given("transferringMemberNumber", "M-3101000")

View File

@ -19,7 +19,7 @@ public class CreateCoopAssetsTransferTransaction extends CreateCoopAssetsTransac
.given("emailAddress", "board-of-directors@new-ag.example.org")
);
requires("Membership: New AG", alias -> new CreateMembership(testSuite)
requires("Membership: %{adoptingMemberNumber} - New AG", alias -> new CreateMembership(testSuite)
.given("memberNumber", toPartnerNumber("%{adoptingMemberNumber}"))
.given("partnerName", "New AG")
.given("validFrom", "2024-11-15")

View File

@ -1,10 +1,15 @@
package net.hostsharing.hsadminng.test.scenarios;
import lombok.experimental.UtilityClass;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.HashSet;
import java.util.Set;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.Arrays.asList;
@Target(METHOD)
@Retention(RUNTIME)
@ -13,4 +18,29 @@ public @interface Produces {
String explicitly() default ""; // same as value
String[] implicitly() default {};
boolean permanent() default true; // false means that the object gets deleted again in the process
@UtilityClass
final class Aggregator {
public static Set<String> producedAliases(final Produces producesAnnot) {
return allOf(
producesAnnot.value(),
producesAnnot.explicitly(),
producesAnnot.implicitly());
}
private Set<String> allOf(final String value, final String explicitly, final String[] implicitly) {
final var all = new HashSet<String>();
if (!value.isEmpty()) {
all.add(value);
}
if (!explicitly.isEmpty()) {
all.add(explicitly);
}
all.addAll(asList(implicitly));
return all;
}
}
}

View File

@ -15,24 +15,22 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.testcontainers.shaded.org.apache.commons.lang3.ObjectUtils;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.test.scenarios.Produces.Aggregator.producedAliases;
import static net.hostsharing.hsadminng.test.scenarios.TemplateResolver.Resolver.DROP_COMMENTS;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.assertj.core.api.Assertions.assertThat;
@ -56,7 +54,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
@Override
public String toString() {
return ObjectUtils.toString(uuid);
return Objects.toString(uuid);
}
}
@ -77,7 +75,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
@SneakyThrows
@BeforeEach
void init(final TestInfo testInfo) {
void beforeScenario(final TestInfo testInfo) {
createHostsharingPerson();
try {
testInfo.getTestMethod().ifPresent(currentTestMethod -> {
@ -91,7 +89,20 @@ public abstract class ScenarioTest extends ContextBasedTest {
}
@AfterEach
void cleanup() { // final TestInfo testInfo
void afterScenario(final TestInfo testInfo) { // final TestInfo testInfo
testInfo.getTestMethod() .ifPresent(currentTestMethod -> {
// FIXME: extract to method
final var producesAnnot = currentTestMethod.getAnnotation(Produces.class);
if (producesAnnot != null && producesAnnot.permanent()) {
final var testMethodProduces = producedAliases(producesAnnot);
testMethodProduces.forEach(declaredAlias ->
assertThat(knowVariables().containsKey(declaredAlias))
.as("@Producer method " + currentTestMethod.getName() +
" did declare but not produce \"" + declaredAlias + "\"")
.isTrue() );
}
});
properties.clear();
testReport.close();
}
@ -122,10 +133,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
if (testMethodRequires != null) {
for (Method potentialProducerMethod : getPotentialProducerMethods()) {
final var producesAnnot = potentialProducerMethod.getAnnotation(Produces.class);
final var testMethodProduces = allOf(
producesAnnot.value(),
producesAnnot.explicitly(),
producesAnnot.implicitly());
final var testMethodProduces = producedAliases(producesAnnot);
// @formatter:off
if ( // that method can produce something required
testMethodProduces.contains(testMethodRequires) &&
@ -141,10 +149,6 @@ public abstract class ScenarioTest extends ContextBasedTest {
// and finally we call the producer method
invokeProducerMethod(this, potentialProducerMethod);
assertThat(knowVariables().containsKey(testMethodRequires))
.as("@Producer method " + potentialProducerMethod.getName() + " did declare but not produce \"" + testMethodRequires + "\"")
.isTrue();
}
// @formatter:on
}
@ -157,7 +161,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
private void keepProducesAlias(final Method currentTestMethod) {
final var producesAnnot = currentTestMethod.getAnnotation(Produces.class);
if ( producesAnnot != null ) {
if (producesAnnot != null) {
final var producesAlias = isNotBlank(producesAnnot.value()) ? producesAnnot.value() : producesAnnot.explicitly();
assertThat(producesAlias)
.as(currentTestMethod.getName() + " must define either value or explicit for @Produces")
@ -191,18 +195,6 @@ public abstract class ScenarioTest extends ContextBasedTest {
}
}
private Set<String> allOf(final String value, final String explicitly, final String[] implicitly) {
final var all = new HashSet<String>();
if (!value.isEmpty()) {
all.add(value);
}
if (!explicitly.isEmpty()) {
all.add(explicitly);
}
all.addAll(asList(implicitly));
return all;
}
static boolean containsAlias(final String alias) {
return aliases.containsKey(alias);
}

View File

@ -71,9 +71,7 @@ public abstract class UseCase<T extends UseCase<?>> {
}
public final void requires(final String alias, final Function<String, UseCase<?>> useCaseFactory) {
if (!ScenarioTest.containsAlias(alias)) {
requirements.put(alias, useCaseFactory);
}
requirements.put(alias, useCaseFactory);
}
public final HttpResponse doRun() {
@ -89,8 +87,9 @@ public abstract class UseCase<T extends UseCase<?>> {
testReport.printLine("");
testReport.silent(() ->
requirements.forEach((alias, factory) -> {
if (!ScenarioTest.containsAlias(alias)) {
factory.apply(alias).run().keepAs(alias);
final var resolvedAlias = ScenarioTest.resolve(alias, DROP_COMMENTS);
if (!ScenarioTest.containsAlias(resolvedAlias)) {
factory.apply(resolvedAlias).run().keepAs(resolvedAlias);
}
})
);