diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/EntityPatch.java b/src/main/java/net/hostsharing/hsadminng/EntityPatch.java similarity index 55% rename from src/main/java/net/hostsharing/hsadminng/hs/office/partner/EntityPatch.java rename to src/main/java/net/hostsharing/hsadminng/EntityPatch.java index b9ec6ac5..a21c931d 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/EntityPatch.java +++ b/src/main/java/net/hostsharing/hsadminng/EntityPatch.java @@ -1,4 +1,4 @@ -package net.hostsharing.hsadminng.hs.office.partner; +package net.hostsharing.hsadminng; public interface EntityPatch { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java index 96aa5137..9893807b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java @@ -1,5 +1,6 @@ package net.hostsharing.hsadminng.hs.office.partner; +import net.hostsharing.hsadminng.EntityPatch; import net.hostsharing.hsadminng.OptionalFromJson; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatch.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatch.java index e06e2a1d..659011a2 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatch.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatch.java @@ -3,10 +3,11 @@ package net.hostsharing.hsadminng.hs.office.person; import net.hostsharing.hsadminng.OptionalFromJson; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource; +import net.hostsharing.hsadminng.EntityPatch; import java.util.Optional; -class HsOfficePersonEntityPatch { +class HsOfficePersonEntityPatch implements EntityPatch { private final HsOfficePersonEntity entity; @@ -14,7 +15,8 @@ class HsOfficePersonEntityPatch { this.entity = entity; } - void apply(final HsOfficePersonPatchResource resource) { + @Override + public void apply(final HsOfficePersonPatchResource resource) { Optional.ofNullable(resource.getPersonType()) .map(HsOfficePersonTypeResource::getValue) .map(HsOfficePersonType::valueOf) diff --git a/src/test/java/net/hostsharing/hsadminng/PatchUnitTestBase.java b/src/test/java/net/hostsharing/hsadminng/PatchUnitTestBase.java new file mode 100644 index 00000000..6eaea7d2 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/PatchUnitTestBase.java @@ -0,0 +1,312 @@ +package net.hostsharing.hsadminng; + +import org.junit.jupiter.api.Named; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.openapitools.jackson.nullable.JsonNullable; + +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowableOfType; +import static org.assertj.core.api.Assumptions.assumeThat; + +public abstract class PatchUnitTestBase { + + @Test + void willPatchNoProperty() { + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + + // when + createPatcher(givenEntity).apply(patchResource); + + // then + final var expectedEntity = newInitialEntity(); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); + } + + @Test + @SuppressWarnings("unchecked") + void willPatchAllProperties() { + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + propertyTestDescriptors().forEach(testCase -> + testCase.patchResource(patchResource) + ); + + // when + createPatcher(givenEntity).apply(patchResource); + + // then + final var expectedEntity = newInitialEntity(); + propertyTestDescriptors().forEach(testCase -> + testCase.updateEntity(expectedEntity) + ); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); + } + + @ParameterizedTest + @MethodSource("propertyTestCases") + void willPatchOnlyGivenProperty(final Property testCase) { + + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + testCase.patchResource(patchResource); + + // when + createPatcher(givenEntity).apply(patchResource); + + // then + final var expectedEntity = newInitialEntity(); + testCase.updateEntity(expectedEntity); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); + } + + @ParameterizedTest + @MethodSource("propertyTestCases") + void willThrowIfUUidCannotBeResolved(final Property testCase) { + assumeThat(testCase.resolvesUuid).isTrue(); + + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + final var givenPatchValue = UUID.fromString("11111111-1111-1111-1111-111111111111"); + testCase.patchResourceWithExplicitValue(patchResource, givenPatchValue); + + // when + final var exception = catchThrowableOfType(() -> { + createPatcher(givenEntity).apply(patchResource); + }, NoSuchElementException.class); + + // then + assertThat(exception).isInstanceOf(NoSuchElementException.class) + .hasMessage("cannot find '" + testCase.name + "' uuid " + givenPatchValue); + } + + @ParameterizedTest + @MethodSource("propertyTestCases") + void willThrowExceptionIfNotNullableUuidIsNull(final Property testCase) { + assumeThat(testCase.resolvesUuid).isTrue(); + assumeThat(testCase.nullable).isFalse(); + + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + testCase.patchResourceToNullValue(patchResource); + + // when + final var actualException = catchThrowableOfType( + () -> createPatcher(givenEntity).apply(patchResource), + IllegalArgumentException.class); + + // then + assertThat(actualException).hasMessage("property '" + testCase.name + "' must not be null"); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(newInitialEntity()); + } + + @ParameterizedTest + @MethodSource("propertyTestCases") + void willPatchOnlyGivenPropertyToNull(final Property testCase) { + assumeThat(testCase.nullable).isTrue(); + + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + testCase.patchResourceToNullValue(patchResource); + + // when + createPatcher(givenEntity).apply(patchResource); + + // then + final var expectedEntity = newInitialEntity(); + testCase.entitySetter.accept(expectedEntity, null); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); + } + + @ParameterizedTest + @MethodSource("propertyTestCases") + void willNotPatchIfGivenPropertyNotGiven(final Property testCase) { + + // given + final var givenEntity = newInitialEntity(); + final var patchResource = newPatchResource(); + testCase.patchResourceToNotGiven(patchResource); + + // when + createPatcher(givenEntity).apply(patchResource); + + // then + final var expectedEntity = newInitialEntity(); + assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); + } + + protected abstract E newInitialEntity(); + + protected abstract R newPatchResource(); + + protected abstract EntityPatch createPatcher(final E entity); + + @SuppressWarnings("rawtypes") + protected abstract Stream propertyTestDescriptors(); + + private Stream propertyTestCases() { + return propertyTestDescriptors() + .map(tc -> Arguments.of(Named.of(tc.name, tc))); + } + + protected static abstract class Property { + + protected final String name; + protected final BiConsumer entitySetter; + protected final EV expectedPatchValue; + protected boolean nullable = true; + private boolean resolvesUuid = false; + + protected Property( + final String name, + final BiConsumer entitySetter, + final EV givenPatchValue) { + this.name = name; + + this.entitySetter = entitySetter; + this.expectedPatchValue = givenPatchValue; + } + + protected abstract void patchResource(R patchResource); + + protected abstract void patchResourceToNullValue(R patchResource); + + protected abstract void patchResourceToNotGiven(R patchResource); + + protected abstract void patchResourceWithExplicitValue(final R patchResource, final RV explicitPatchValue); + + void updateEntity(final E expectedEntity) { + entitySetter.accept(expectedEntity, expectedPatchValue); + } + + public Property notNullable() { + nullable = false; + return this; + } + + public Property resolvesUuid() { + resolvesUuid = true; + return this; + } + + @SuppressWarnings("unchecked") + protected static EV sameAs(final RV givenResourceValue) { + return (EV) givenResourceValue; + } + } + + protected static class SimpleProperty extends Property { + + public final RV givenPatchValue; + private final BiConsumer resourceSetter; + + public SimpleProperty( + final String name, + final BiConsumer resourceSetter, + final RV givenPatchValue, + final BiConsumer entitySetter + ) { + super(name, entitySetter, sameAs(givenPatchValue)); + this.resourceSetter = resourceSetter; + this.givenPatchValue = givenPatchValue; + } + + public SimpleProperty( + final String name, + final BiConsumer resourceSetter, + final RV givenPatchValue, + final BiConsumer entitySetter, + final EV expectedPatchValue + ) { + super(name, entitySetter, expectedPatchValue); + this.resourceSetter = resourceSetter; + this.givenPatchValue = givenPatchValue; + } + + @Override + protected void patchResource(final R patchResource) { + resourceSetter.accept(patchResource, givenPatchValue); + } + + @Override + protected void patchResourceToNullValue(final R patchResource) { + assertThat(nullable).isTrue(); // null can mean "not given" or "null value", not both + resourceSetter.accept(patchResource, null); + } + + @Override + protected void patchResourceToNotGiven(final R patchResource) { + assertThat(nullable).isFalse(); // null can mean "not given" or "null value", not both + resourceSetter.accept(patchResource, null); + } + + @Override + protected void patchResourceWithExplicitValue(final R patchResource, final RV explicitPatchValue) { + resourceSetter.accept(patchResource, explicitPatchValue); + } + } + + protected static class JsonNullableProperty extends Property { + + private final BiConsumer> resourceSetter; + public final RV givenPatchValue; + + public JsonNullableProperty( + final String name, + final BiConsumer> resourceSetter, + final RV givenPatchValue, + final BiConsumer entitySetter + ) { + super(name, entitySetter, sameAs(givenPatchValue)); + this.resourceSetter = resourceSetter; + this.givenPatchValue = givenPatchValue; + } + + public JsonNullableProperty( + final String name, + final BiConsumer> resourceSetter, + final RV givenPatchValue, + final BiConsumer entitySetter, + final EV expectedPatchValue + ) { + super(name, entitySetter, expectedPatchValue); + this.resourceSetter = resourceSetter; + this.givenPatchValue = givenPatchValue; + } + + @Override + protected void patchResource(final R patchResource) { + resourceSetter.accept(patchResource, JsonNullable.of(givenPatchValue)); + } + + @Override + protected void patchResourceToNullValue(final R patchResource) { + resourceSetter.accept(patchResource, JsonNullable.of(null)); + } + + @Override + protected void patchResourceToNotGiven(final R patchResource) { + resourceSetter.accept(patchResource, null); + } + + @Override + protected void patchResourceWithExplicitValue(final R patchResource, final RV explicitPatchValue) { + resourceSetter.accept(patchResource, JsonNullable.of(explicitPatchValue)); + + } + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java index 9bba6ea1..a1460c76 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java @@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.office.partner; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; +import net.hostsharing.hsadminng.PatchUnitTestBase; import org.junit.jupiter.api.TestInstance; import java.time.LocalDate; @@ -38,26 +39,26 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase< .build(); @Override - HsOfficePartnerEntity newInitialEntity() { - final var p = new HsOfficePartnerEntity(); - p.setUuid(INITIAL_PARTNER_UUID); - p.setPerson(givenInitialPerson); - p.setContact(givenInitialContact); - p.setRegistrationOffice("initial Reg-Office"); - p.setRegistrationNumber("initial Reg-Number"); - p.setBirthday(INITIAL_BIRTHDAY); - p.setBirthName("initial birth name"); - p.setDateOfDeath(INITIAL_DAY_OF_DEATH); - return p; + protected HsOfficePartnerEntity newInitialEntity() { + final var entity = new HsOfficePartnerEntity(); + entity.setUuid(INITIAL_PARTNER_UUID); + entity.setPerson(givenInitialPerson); + entity.setContact(givenInitialContact); + entity.setRegistrationOffice("initial Reg-Office"); + entity.setRegistrationNumber("initial Reg-Number"); + entity.setBirthday(INITIAL_BIRTHDAY); + entity.setBirthName("initial birth name"); + entity.setDateOfDeath(INITIAL_DAY_OF_DEATH); + return entity; } @Override - HsOfficePartnerPatchResource newPatchResource() { + protected HsOfficePartnerPatchResource newPatchResource() { return new HsOfficePartnerPatchResource(); } @Override - HsOfficePartnerEntityPatch createPatcher(final HsOfficePartnerEntity partner) { + protected HsOfficePartnerEntityPatch createPatcher(final HsOfficePartnerEntity partner) { return new HsOfficePartnerEntityPatch( partner, uuid -> uuid == PATCHED_CONTACT_UUID @@ -69,9 +70,9 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase< } @Override - Stream testCases() { + protected Stream propertyTestDescriptors() { return Stream.of( - new TestCase( + new JsonNullableProperty<>( "contact", HsOfficePartnerPatchResource::setContactUuid, PATCHED_CONTACT_UUID, @@ -79,7 +80,7 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase< newContact(PATCHED_CONTACT_UUID)) .notNullable() .resolvesUuid(), - new TestCase( + new JsonNullableProperty<>( "person", HsOfficePartnerPatchResource::setPersonUuid, PATCHED_PERSON_UUID, @@ -87,17 +88,17 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase< newPerson(PATCHED_PERSON_UUID)) .notNullable() .resolvesUuid(), - new TestCase( + new JsonNullableProperty<>( "registrationOffice", HsOfficePartnerPatchResource::setRegistrationOffice, "patched Reg-Office", HsOfficePartnerEntity::setRegistrationOffice), - new TestCase( + new JsonNullableProperty<>( "birthday", HsOfficePartnerPatchResource::setBirthday, PATCHED_BIRTHDAY, HsOfficePartnerEntity::setBirthday), - new TestCase( + new JsonNullableProperty<>( "dayOfDeath", HsOfficePartnerPatchResource::setDateOfDeath, PATCHED_DATE_OF_DEATH, diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/PatchUnitTestBase.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/PatchUnitTestBase.java deleted file mode 100644 index 2ec6d0f9..00000000 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/PatchUnitTestBase.java +++ /dev/null @@ -1,210 +0,0 @@ -package net.hostsharing.hsadminng.hs.office.partner; - -import org.junit.jupiter.api.Named; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.openapitools.jackson.nullable.JsonNullable; - -import java.util.NoSuchElementException; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowableOfType; -import static org.assertj.core.api.Assumptions.assumeThat; - -public abstract class PatchUnitTestBase { - - @Test - void willPatchNoProperty() { - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - - // when - createPatcher(givenEntity).apply(patchResource); - - // then - final var expectedEntity = newInitialEntity(); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); - } - - @Test - void willPatchAllProperties() { - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - testCases().forEach(testCase -> - testCase.resourceSetter.accept(patchResource, JsonNullable.of(testCase.givenPatchedValue)) - ); - - // when - createPatcher(givenEntity).apply(patchResource); - - // then - final var expectedEntity = newInitialEntity(); - testCases().forEach(testCase -> - testCase.entitySetter.accept(expectedEntity, testCase.expectedPatchValue) - ); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); - } - - @ParameterizedTest - @MethodSource("testCaseArguments") - void willPatchOnlyGivenProperty(final TestCase testCase) { - - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - testCase.resourceSetter.accept(patchResource, JsonNullable.of(testCase.givenPatchedValue)); - - // when - createPatcher(givenEntity).apply(patchResource); - - // then - final var expectedEntity = newInitialEntity(); - testCase.entitySetter.accept(expectedEntity, testCase.expectedPatchValue); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); - } - - @ParameterizedTest - @MethodSource("testCaseArguments") - void willThrowIfUUidCannotBeResolved(final TestCase testCase) { - assumeThat(testCase.resolvesUuid).isTrue(); - - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - final var givenPatchValue = UUID.fromString("11111111-1111-1111-1111-111111111111"); - testCase.resourceSetter.accept(patchResource, JsonNullable.of(givenPatchValue)); - - // when - final var exception = catchThrowableOfType(() -> { - createPatcher(givenEntity).apply(patchResource); - }, NoSuchElementException.class); - - // then - assertThat(exception).isInstanceOf(NoSuchElementException.class) - .hasMessage("cannot find '" + testCase.name + "' uuid " + givenPatchValue); - } - - @ParameterizedTest - @MethodSource("testCaseArguments") - void willPatchOnlyGivenPropertyToNull(final TestCase testCase) { - assumeThat(testCase.nullable).isTrue(); - - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - testCase.resourceSetter.accept(patchResource, JsonNullable.of(null)); - - // when - createPatcher(givenEntity).apply(patchResource); - - // then - final var expectedEntity = newInitialEntity(); - testCase.entitySetter.accept(expectedEntity, null); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); - } - - @ParameterizedTest - @MethodSource("testCaseArguments") - void willThrowExceptionIfResourcePropertyIsNull(final TestCase testCase) { - assumeThat(testCase.nullable).isFalse(); - - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - testCase.resourceSetter.accept(patchResource, JsonNullable.of(null)); - - // when - final var actualException = catchThrowableOfType( - () -> createPatcher(givenEntity).apply(patchResource), - IllegalArgumentException.class); - - // then - assertThat(actualException).hasMessage("property '" + testCase.name + "' must not be null"); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(newInitialEntity()); - } - - @ParameterizedTest - @MethodSource("testCaseArguments") - void willNotPatchIfGivenPropertyNotGiven(final TestCase testCase) { - - // given - final var givenEntity = newInitialEntity(); - final var patchResource = newPatchResource(); - testCase.resourceSetter.accept(patchResource, null); - - // when - createPatcher(givenEntity).apply(patchResource); - - // then - final var expectedEntity = newInitialEntity(); - assertThat(givenEntity).usingRecursiveComparison().isEqualTo(expectedEntity); - } - - abstract E newInitialEntity(); - - abstract R newPatchResource(); - - abstract EntityPatch createPatcher(final E entity); - - abstract Stream testCases(); - - Stream testCaseArguments() { - return testCases().map(tc -> Arguments.of(Named.of(tc.name, tc))); - } - - class TestCase { - - private final String name; - public final Object givenPatchedValue; - private final BiConsumer> resourceSetter; - private final BiConsumer entitySetter; - private final Object expectedPatchValue; - - private boolean nullable = true; - private boolean resolvesUuid = false; - - TestCase( - final String name, - final BiConsumer> resourceSetter, - final V givenPatchValue, - final BiConsumer entitySetter - ) { - this.name = name; - this.resourceSetter = (BiConsumer>) (BiConsumer) resourceSetter; - this.givenPatchedValue = givenPatchValue; - this.entitySetter = (BiConsumer) entitySetter; - this.expectedPatchValue = givenPatchValue; - } - - TestCase( - final String name, - final BiConsumer> resourceSetter, - final V givenPatchValue, - final BiConsumer entitySetter, - final S expectedPatchValue - ) { - this.name = name; - this.resourceSetter = (BiConsumer>) (BiConsumer) resourceSetter; - this.givenPatchedValue = givenPatchValue; - this.entitySetter = (BiConsumer) entitySetter; - this.expectedPatchValue = expectedPatchValue; - } - - TestCase notNullable() { - nullable = false; - return this; - } - - TestCase resolvesUuid() { - resolvesUuid = true; - return this; - } - } -} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatchUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatchUnitTest.java index d0f93f50..bf3d9c83 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatchUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntityPatchUnitTest.java @@ -1,153 +1,70 @@ package net.hostsharing.hsadminng.hs.office.person; +import net.hostsharing.hsadminng.PatchUnitTestBase; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.NullSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.openapitools.jackson.nullable.JsonNullable; +import org.junit.jupiter.api.TestInstance; import java.util.UUID; +import java.util.stream.Stream; -import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; -// TODO: there must be an easier way to test such patch classes -class HsOfficePersonEntityPatchUnitTest { +@TestInstance(PER_CLASS) +class HsOfficePersonEntityPatchUnitTest extends PatchUnitTestBase< + HsOfficePersonPatchResource, + HsOfficePersonEntity + > { private static final UUID INITIAL_PERSON_UUID = UUID.randomUUID(); - final HsOfficePersonEntity givenPerson = new HsOfficePersonEntity(); - final HsOfficePersonPatchResource patchResource = new HsOfficePersonPatchResource(); - private final HsOfficePersonEntityPatch hsOfficePersonEntityPatch = - new HsOfficePersonEntityPatch(givenPerson); - - { - givenPerson.setUuid(INITIAL_PERSON_UUID); - givenPerson.setPersonType(HsOfficePersonType.LEGAL); - givenPerson.setTradeName("initial@example.org"); - givenPerson.setFamilyName("initial postal address"); - givenPerson.setGivenName("+01 100 123456789"); + @Override + protected HsOfficePersonEntity newInitialEntity() { + final var entity = new HsOfficePersonEntity(); + entity.setUuid(INITIAL_PERSON_UUID); + entity.setPersonType(HsOfficePersonType.LEGAL); + entity.setTradeName("initial@example.org"); + entity.setFamilyName("initial postal address"); + entity.setGivenName("+01 100 123456789"); + return entity; } - @Test - void willPatchAllProperties() { - // given - patchResource.setPersonType(HsOfficePersonTypeResource.NATURAL); - patchResource.setTradeName(JsonNullable.of("patched@example.org")); - patchResource.setFamilyName(JsonNullable.of("patched postal address")); - patchResource.setGivenName(JsonNullable.of("+01 200 987654321")); - - // when - hsOfficePersonEntityPatch.apply(patchResource); - - // then - new HsOfficePersonEntityMatcher() - .withPatchedPersonType(HsOfficePersonType.NATURAL) - .withPatchedTradeName("patched@example.org") - .withPatchedFamilyName("patched postal address") - .withPatchedGivenName("+01 200 987654321") - .matches(givenPerson); + @Override + protected HsOfficePersonPatchResource newPatchResource() { + return new HsOfficePersonPatchResource(); } - @ParameterizedTest - @EnumSource(HsOfficePersonTypeResource.class) - void willPatchOnlyPersonTypeProperty(final HsOfficePersonTypeResource patchedValue) { - // given - patchResource.setPersonType(patchedValue); - - // when - hsOfficePersonEntityPatch.apply(patchResource); - - // then - new HsOfficePersonEntityMatcher() - .withPatchedPersonType(HsOfficePersonType.valueOf(patchedValue.getValue())) - .matches(givenPerson); + @Override + protected HsOfficePersonEntityPatch createPatcher(final HsOfficePersonEntity entity) { + return new HsOfficePersonEntityPatch(entity); } - @ParameterizedTest - @ValueSource(strings = { "patched@example.org" }) - @NullSource - void willPatchOnlyTradeNameProperty(final String patchedValue) { - // given - patchResource.setTradeName(JsonNullable.of(patchedValue)); - - // when - hsOfficePersonEntityPatch.apply(patchResource); - - // then - new HsOfficePersonEntityMatcher() - .withPatchedTradeName(patchedValue) - .matches(givenPerson); + @Override + protected Stream propertyTestDescriptors() { + return Stream.of( + new SimpleProperty<>( + "personType", + HsOfficePersonPatchResource::setPersonType, + HsOfficePersonTypeResource.SOLE_REPRESENTATION, + HsOfficePersonEntity::setPersonType, + HsOfficePersonType.SOLE_REPRESENTATION) + .notNullable(), + new JsonNullableProperty<>( + "tradeName", + HsOfficePersonPatchResource::setTradeName, + "patched trade name", + HsOfficePersonEntity::setTradeName), + new JsonNullableProperty<>( + "familyName", + HsOfficePersonPatchResource::setFamilyName, + "patched family name", + HsOfficePersonEntity::setFamilyName), + new JsonNullableProperty<>( + "patched given name", + HsOfficePersonPatchResource::setGivenName, + "patched given name", + HsOfficePersonEntity::setGivenName) + ); } - @ParameterizedTest - @ValueSource(strings = { "patched postal address" }) - @NullSource - void willPatchOnlyFamilyNameProperty(final String patchedValue) { - // given - patchResource.setFamilyName(JsonNullable.of(patchedValue)); - - // when - hsOfficePersonEntityPatch.apply(patchResource); - - // then - new HsOfficePersonEntityMatcher() - .withPatchedFamilyName(patchedValue) - .matches(givenPerson); - } - - @ParameterizedTest - @ValueSource(strings = { "+01 200 987654321" }) - @NullSource - void willPatchOnlyGivenNameProperty(final String patchedValue) { - // given - patchResource.setGivenName(JsonNullable.of(patchedValue)); - - // when - hsOfficePersonEntityPatch.apply(patchResource); - - // then - new HsOfficePersonEntityMatcher() - .withPatchedGivenName(patchedValue) - .matches(givenPerson); - } - - private static class HsOfficePersonEntityMatcher { - - private HsOfficePersonType expectedPersonType = HsOfficePersonType.LEGAL; - private String expectedTradeName = "initial@example.org"; - private String expectedFamilyName = "initial postal address"; - - private String expectedGivenName = "+01 100 123456789"; - - HsOfficePersonEntityMatcher withPatchedPersonType(final HsOfficePersonType patchedPersonType) { - expectedPersonType = patchedPersonType; - return this; - } - - HsOfficePersonEntityMatcher withPatchedTradeName(final String patchedTradeName) { - expectedTradeName = patchedTradeName; - return this; - } - - HsOfficePersonEntityMatcher withPatchedFamilyName(final String patchedFamilyName) { - expectedFamilyName = patchedFamilyName; - return this; - } - - HsOfficePersonEntityMatcher withPatchedGivenName(final String patchedGivenName) { - expectedGivenName = patchedGivenName; - return this; - } - - void matches(final HsOfficePersonEntity givenPerson) { - - assertThat(givenPerson.getPersonType()).isEqualTo(expectedPersonType); - assertThat(givenPerson.getTradeName()).isEqualTo(expectedTradeName); - assertThat(givenPerson.getFamilyName()).isEqualTo(expectedFamilyName); - assertThat(givenPerson.getGivenName()).isEqualTo(expectedGivenName); - } - } }