refactor HsOfficePersonEntityPatchUnitTest to PatchUnitTestBase

This commit is contained in:
Michael Hoennig 2022-09-25 11:12:36 +02:00
parent 3e6da45302
commit b431a6653d
7 changed files with 388 additions and 365 deletions

View File

@ -1,4 +1,4 @@
package net.hostsharing.hsadminng.hs.office.partner; package net.hostsharing.hsadminng;
public interface EntityPatch<R> { public interface EntityPatch<R> {

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.partner; package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.EntityPatch;
import net.hostsharing.hsadminng.OptionalFromJson; import net.hostsharing.hsadminng.OptionalFromJson;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; 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.generated.api.v1.model.HsOfficePartnerPatchResource;

View File

@ -3,10 +3,11 @@ package net.hostsharing.hsadminng.hs.office.person;
import net.hostsharing.hsadminng.OptionalFromJson; 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.HsOfficePersonPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource;
import net.hostsharing.hsadminng.EntityPatch;
import java.util.Optional; import java.util.Optional;
class HsOfficePersonEntityPatch { class HsOfficePersonEntityPatch implements EntityPatch<HsOfficePersonPatchResource> {
private final HsOfficePersonEntity entity; private final HsOfficePersonEntity entity;
@ -14,7 +15,8 @@ class HsOfficePersonEntityPatch {
this.entity = entity; this.entity = entity;
} }
void apply(final HsOfficePersonPatchResource resource) { @Override
public void apply(final HsOfficePersonPatchResource resource) {
Optional.ofNullable(resource.getPersonType()) Optional.ofNullable(resource.getPersonType())
.map(HsOfficePersonTypeResource::getValue) .map(HsOfficePersonTypeResource::getValue)
.map(HsOfficePersonType::valueOf) .map(HsOfficePersonType::valueOf)

View File

@ -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<R, E> {
@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<R, Object, E, Object> 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<R, Object, E, Object> 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<R, Object, E, Object> 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<R, Object, E, Object> 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<R, Object, E, Object> 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<R> createPatcher(final E entity);
@SuppressWarnings("rawtypes")
protected abstract Stream<Property> propertyTestDescriptors();
private Stream<Arguments> propertyTestCases() {
return propertyTestDescriptors()
.map(tc -> Arguments.of(Named.of(tc.name, tc)));
}
protected static abstract class Property<R, RV, E, EV> {
protected final String name;
protected final BiConsumer<E, EV> entitySetter;
protected final EV expectedPatchValue;
protected boolean nullable = true;
private boolean resolvesUuid = false;
protected Property(
final String name,
final BiConsumer<E, EV> 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<R, RV, E, EV> notNullable() {
nullable = false;
return this;
}
public Property<R, RV, E, EV> resolvesUuid() {
resolvesUuid = true;
return this;
}
@SuppressWarnings("unchecked")
protected static <EV, RV> EV sameAs(final RV givenResourceValue) {
return (EV) givenResourceValue;
}
}
protected static class SimpleProperty<R, RV, E, EV> extends Property<R, RV, E, EV> {
public final RV givenPatchValue;
private final BiConsumer<R, RV> resourceSetter;
public SimpleProperty(
final String name,
final BiConsumer<R, RV> resourceSetter,
final RV givenPatchValue,
final BiConsumer<E, EV> entitySetter
) {
super(name, entitySetter, sameAs(givenPatchValue));
this.resourceSetter = resourceSetter;
this.givenPatchValue = givenPatchValue;
}
public SimpleProperty(
final String name,
final BiConsumer<R, RV> resourceSetter,
final RV givenPatchValue,
final BiConsumer<E, EV> 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<R, RV, E, EV> extends Property<R, RV, E, EV> {
private final BiConsumer<R, JsonNullable<RV>> resourceSetter;
public final RV givenPatchValue;
public JsonNullableProperty(
final String name,
final BiConsumer<R, JsonNullable<RV>> resourceSetter,
final RV givenPatchValue,
final BiConsumer<E, EV> entitySetter
) {
super(name, entitySetter, sameAs(givenPatchValue));
this.resourceSetter = resourceSetter;
this.givenPatchValue = givenPatchValue;
}
public JsonNullableProperty(
final String name,
final BiConsumer<R, JsonNullable<RV>> resourceSetter,
final RV givenPatchValue,
final BiConsumer<E, EV> 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));
}
}
}

View File

@ -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.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.PatchUnitTestBase;
import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance;
import java.time.LocalDate; import java.time.LocalDate;
@ -38,26 +39,26 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase<
.build(); .build();
@Override @Override
HsOfficePartnerEntity newInitialEntity() { protected HsOfficePartnerEntity newInitialEntity() {
final var p = new HsOfficePartnerEntity(); final var entity = new HsOfficePartnerEntity();
p.setUuid(INITIAL_PARTNER_UUID); entity.setUuid(INITIAL_PARTNER_UUID);
p.setPerson(givenInitialPerson); entity.setPerson(givenInitialPerson);
p.setContact(givenInitialContact); entity.setContact(givenInitialContact);
p.setRegistrationOffice("initial Reg-Office"); entity.setRegistrationOffice("initial Reg-Office");
p.setRegistrationNumber("initial Reg-Number"); entity.setRegistrationNumber("initial Reg-Number");
p.setBirthday(INITIAL_BIRTHDAY); entity.setBirthday(INITIAL_BIRTHDAY);
p.setBirthName("initial birth name"); entity.setBirthName("initial birth name");
p.setDateOfDeath(INITIAL_DAY_OF_DEATH); entity.setDateOfDeath(INITIAL_DAY_OF_DEATH);
return p; return entity;
} }
@Override @Override
HsOfficePartnerPatchResource newPatchResource() { protected HsOfficePartnerPatchResource newPatchResource() {
return new HsOfficePartnerPatchResource(); return new HsOfficePartnerPatchResource();
} }
@Override @Override
HsOfficePartnerEntityPatch createPatcher(final HsOfficePartnerEntity partner) { protected HsOfficePartnerEntityPatch createPatcher(final HsOfficePartnerEntity partner) {
return new HsOfficePartnerEntityPatch( return new HsOfficePartnerEntityPatch(
partner, partner,
uuid -> uuid == PATCHED_CONTACT_UUID uuid -> uuid == PATCHED_CONTACT_UUID
@ -69,9 +70,9 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase<
} }
@Override @Override
Stream<TestCase> testCases() { protected Stream<Property> propertyTestDescriptors() {
return Stream.of( return Stream.of(
new TestCase( new JsonNullableProperty<>(
"contact", "contact",
HsOfficePartnerPatchResource::setContactUuid, HsOfficePartnerPatchResource::setContactUuid,
PATCHED_CONTACT_UUID, PATCHED_CONTACT_UUID,
@ -79,7 +80,7 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase<
newContact(PATCHED_CONTACT_UUID)) newContact(PATCHED_CONTACT_UUID))
.notNullable() .notNullable()
.resolvesUuid(), .resolvesUuid(),
new TestCase( new JsonNullableProperty<>(
"person", "person",
HsOfficePartnerPatchResource::setPersonUuid, HsOfficePartnerPatchResource::setPersonUuid,
PATCHED_PERSON_UUID, PATCHED_PERSON_UUID,
@ -87,17 +88,17 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase<
newPerson(PATCHED_PERSON_UUID)) newPerson(PATCHED_PERSON_UUID))
.notNullable() .notNullable()
.resolvesUuid(), .resolvesUuid(),
new TestCase( new JsonNullableProperty<>(
"registrationOffice", "registrationOffice",
HsOfficePartnerPatchResource::setRegistrationOffice, HsOfficePartnerPatchResource::setRegistrationOffice,
"patched Reg-Office", "patched Reg-Office",
HsOfficePartnerEntity::setRegistrationOffice), HsOfficePartnerEntity::setRegistrationOffice),
new TestCase( new JsonNullableProperty<>(
"birthday", "birthday",
HsOfficePartnerPatchResource::setBirthday, HsOfficePartnerPatchResource::setBirthday,
PATCHED_BIRTHDAY, PATCHED_BIRTHDAY,
HsOfficePartnerEntity::setBirthday), HsOfficePartnerEntity::setBirthday),
new TestCase( new JsonNullableProperty<>(
"dayOfDeath", "dayOfDeath",
HsOfficePartnerPatchResource::setDateOfDeath, HsOfficePartnerPatchResource::setDateOfDeath,
PATCHED_DATE_OF_DEATH, PATCHED_DATE_OF_DEATH,

View File

@ -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<R, E> {
@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<R> createPatcher(final E entity);
abstract Stream<TestCase> testCases();
Stream<Arguments> 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<Object, JsonNullable<?>> resourceSetter;
private final BiConsumer<Object, Object> entitySetter;
private final Object expectedPatchValue;
private boolean nullable = true;
private boolean resolvesUuid = false;
<R, V, E> TestCase(
final String name,
final BiConsumer<R, JsonNullable<V>> resourceSetter,
final V givenPatchValue,
final BiConsumer<E, V> entitySetter
) {
this.name = name;
this.resourceSetter = (BiConsumer<Object, JsonNullable<?>>) (BiConsumer) resourceSetter;
this.givenPatchedValue = givenPatchValue;
this.entitySetter = (BiConsumer<Object, Object>) entitySetter;
this.expectedPatchValue = givenPatchValue;
}
<R, V, E, S> TestCase(
final String name,
final BiConsumer<R, JsonNullable<V>> resourceSetter,
final V givenPatchValue,
final BiConsumer<E, S> entitySetter,
final S expectedPatchValue
) {
this.name = name;
this.resourceSetter = (BiConsumer<Object, JsonNullable<?>>) (BiConsumer) resourceSetter;
this.givenPatchedValue = givenPatchValue;
this.entitySetter = (BiConsumer<Object, Object>) entitySetter;
this.expectedPatchValue = expectedPatchValue;
}
TestCase notNullable() {
nullable = false;
return this;
}
TestCase resolvesUuid() {
resolvesUuid = true;
return this;
}
}
}

View File

@ -1,153 +1,70 @@
package net.hostsharing.hsadminng.hs.office.person; 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.HsOfficePersonPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonTypeResource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance;
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 java.util.UUID; 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 @TestInstance(PER_CLASS)
class HsOfficePersonEntityPatchUnitTest { class HsOfficePersonEntityPatchUnitTest extends PatchUnitTestBase<
HsOfficePersonPatchResource,
HsOfficePersonEntity
> {
private static final UUID INITIAL_PERSON_UUID = UUID.randomUUID(); private static final UUID INITIAL_PERSON_UUID = UUID.randomUUID();
final HsOfficePersonEntity givenPerson = new HsOfficePersonEntity();
final HsOfficePersonPatchResource patchResource = new HsOfficePersonPatchResource();
private final HsOfficePersonEntityPatch hsOfficePersonEntityPatch = @Override
new HsOfficePersonEntityPatch(givenPerson); protected HsOfficePersonEntity newInitialEntity() {
final var entity = new HsOfficePersonEntity();
{ entity.setUuid(INITIAL_PERSON_UUID);
givenPerson.setUuid(INITIAL_PERSON_UUID); entity.setPersonType(HsOfficePersonType.LEGAL);
givenPerson.setPersonType(HsOfficePersonType.LEGAL); entity.setTradeName("initial@example.org");
givenPerson.setTradeName("initial@example.org"); entity.setFamilyName("initial postal address");
givenPerson.setFamilyName("initial postal address"); entity.setGivenName("+01 100 123456789");
givenPerson.setGivenName("+01 100 123456789"); return entity;
} }
@Test @Override
void willPatchAllProperties() { protected HsOfficePersonPatchResource newPatchResource() {
// given return new HsOfficePersonPatchResource();
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);
} }
@ParameterizedTest @Override
@EnumSource(HsOfficePersonTypeResource.class) protected HsOfficePersonEntityPatch createPatcher(final HsOfficePersonEntity entity) {
void willPatchOnlyPersonTypeProperty(final HsOfficePersonTypeResource patchedValue) { return new HsOfficePersonEntityPatch(entity);
// given
patchResource.setPersonType(patchedValue);
// when
hsOfficePersonEntityPatch.apply(patchResource);
// then
new HsOfficePersonEntityMatcher()
.withPatchedPersonType(HsOfficePersonType.valueOf(patchedValue.getValue()))
.matches(givenPerson);
} }
@ParameterizedTest @Override
@ValueSource(strings = { "patched@example.org" }) protected Stream<Property> propertyTestDescriptors() {
@NullSource return Stream.of(
void willPatchOnlyTradeNameProperty(final String patchedValue) { new SimpleProperty<>(
// given "personType",
patchResource.setTradeName(JsonNullable.of(patchedValue)); HsOfficePersonPatchResource::setPersonType,
HsOfficePersonTypeResource.SOLE_REPRESENTATION,
// when HsOfficePersonEntity::setPersonType,
hsOfficePersonEntityPatch.apply(patchResource); HsOfficePersonType.SOLE_REPRESENTATION)
.notNullable(),
// then new JsonNullableProperty<>(
new HsOfficePersonEntityMatcher() "tradeName",
.withPatchedTradeName(patchedValue) HsOfficePersonPatchResource::setTradeName,
.matches(givenPerson); "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);
}
}
} }