refactor HsOfficeContactEntityPatcherUnitTest to PatchUnitTestBase

This commit is contained in:
Michael Hoennig 2022-09-25 11:37:46 +02:00
parent b431a6653d
commit d13f0cbcdf
11 changed files with 86 additions and 173 deletions

View File

@ -1,6 +1,6 @@
package net.hostsharing.hsadminng; package net.hostsharing.hsadminng;
public interface EntityPatch<R> { public interface EntityPatcher<R> {
void apply(R resource); void apply(R resource);
} }

View File

@ -1,9 +1,10 @@
package net.hostsharing.hsadminng.hs.office.contact; package net.hostsharing.hsadminng.hs.office.contact;
import net.hostsharing.hsadminng.EntityPatcher;
import net.hostsharing.hsadminng.OptionalFromJson; import net.hostsharing.hsadminng.OptionalFromJson;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactPatchResource;
class HsOfficeContactEntityPatch { class HsOfficeContactEntityPatch implements EntityPatcher<HsOfficeContactPatchResource> {
private final HsOfficeContactEntity entity; private final HsOfficeContactEntity entity;
@ -11,7 +12,8 @@ class HsOfficeContactEntityPatch {
this.entity = entity; this.entity = entity;
} }
void apply(final HsOfficeContactPatchResource resource) { @Override
public void apply(final HsOfficeContactPatchResource resource) {
OptionalFromJson.of(resource.getLabel()).ifPresent(entity::setLabel); OptionalFromJson.of(resource.getLabel()).ifPresent(entity::setLabel);
OptionalFromJson.of(resource.getPostalAddress()).ifPresent(entity::setPostalAddress); OptionalFromJson.of(resource.getPostalAddress()).ifPresent(entity::setPostalAddress);
OptionalFromJson.of(resource.getEmailAddresses()).ifPresent(entity::setEmailAddresses); OptionalFromJson.of(resource.getEmailAddresses()).ifPresent(entity::setEmailAddresses);

View File

@ -1,7 +1,6 @@
package net.hostsharing.hsadminng.hs.office.partner; package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.Mapper; import net.hostsharing.hsadminng.Mapper;
import net.hostsharing.hsadminng.OptionalFromJson;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi;
@ -125,7 +124,7 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
final var current = partnerRepo.findByUuid(partnerUuid).orElseThrow(); final var current = partnerRepo.findByUuid(partnerUuid).orElseThrow();
new HsOfficePartnerEntityPatch(current, contactRepo::findByUuid, personRepo::findByUuid).apply(body); new HsOfficePartnerEntityPatcher(current, contactRepo::findByUuid, personRepo::findByUuid).apply(body);
final var saved = partnerRepo.save(current); final var saved = partnerRepo.save(current);
final var mapped = map(saved, HsOfficePartnerResource.class); final var mapped = map(saved, HsOfficePartnerResource.class);

View File

@ -1,6 +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.EntityPatcher;
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;
@ -12,13 +12,13 @@ import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
class HsOfficePartnerEntityPatch implements EntityPatch<HsOfficePartnerPatchResource> { class HsOfficePartnerEntityPatcher implements EntityPatcher<HsOfficePartnerPatchResource> {
private final HsOfficePartnerEntity entity; private final HsOfficePartnerEntity entity;
private final Function<UUID, Optional<HsOfficeContactEntity>> fetchContact; private final Function<UUID, Optional<HsOfficeContactEntity>> fetchContact;
private final Function<UUID, Optional<HsOfficePersonEntity>> fetchPerson; private final Function<UUID, Optional<HsOfficePersonEntity>> fetchPerson;
HsOfficePartnerEntityPatch( HsOfficePartnerEntityPatcher(
final HsOfficePartnerEntity entity, final HsOfficePartnerEntity entity,
final Function<UUID, Optional<HsOfficeContactEntity>> fetchContact, final Function<UUID, Optional<HsOfficeContactEntity>> fetchContact,
final Function<UUID, Optional<HsOfficePersonEntity>> fetchPerson) { final Function<UUID, Optional<HsOfficePersonEntity>> fetchPerson) {

View File

@ -6,7 +6,6 @@ import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePersonsA
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonInsertResource;
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.HsOfficePersonResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonResource;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntityPatch;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -109,7 +108,7 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
final var current = personRepo.findByUuid(personUuid).orElseThrow(); final var current = personRepo.findByUuid(personUuid).orElseThrow();
new HsOfficePersonEntityPatch(current).apply(body); new HsOfficePersonEntityPatcher(current).apply(body);
final var saved = personRepo.save(current); final var saved = personRepo.save(current);
final var mapped = map(saved, HsOfficePersonResource.class); final var mapped = map(saved, HsOfficePersonResource.class);

View File

@ -3,15 +3,15 @@ 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 net.hostsharing.hsadminng.EntityPatcher;
import java.util.Optional; import java.util.Optional;
class HsOfficePersonEntityPatch implements EntityPatch<HsOfficePersonPatchResource> { class HsOfficePersonEntityPatcher implements EntityPatcher<HsOfficePersonPatchResource> {
private final HsOfficePersonEntity entity; private final HsOfficePersonEntity entity;
HsOfficePersonEntityPatch(final HsOfficePersonEntity entity) { HsOfficePersonEntityPatcher(final HsOfficePersonEntity entity) {
this.entity = entity; this.entity = entity;
} }

View File

@ -153,7 +153,7 @@ public abstract class PatchUnitTestBase<R, E> {
protected abstract R newPatchResource(); protected abstract R newPatchResource();
protected abstract EntityPatch<R> createPatcher(final E entity); protected abstract EntityPatcher<R> createPatcher(final E entity);
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
protected abstract Stream<Property> propertyTestDescriptors(); protected abstract Stream<Property> propertyTestDescriptors();

View File

@ -1,152 +0,0 @@
package net.hostsharing.hsadminng.hs.office.contact;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactPatchResource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
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 static org.assertj.core.api.Assertions.assertThat;
// TODO: there must be an easier way to test such patch classes
class HsOfficeContactEntityPatchUnitTest {
private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID();
final HsOfficeContactEntity givenContact = new HsOfficeContactEntity();
final HsOfficeContactPatchResource patchResource = new HsOfficeContactPatchResource();
private final HsOfficeContactEntityPatch hsOfficeContactEntityPatch =
new HsOfficeContactEntityPatch(givenContact);
{
givenContact.setUuid(INITIAL_CONTACT_UUID);
givenContact.setLabel("initial label");
givenContact.setEmailAddresses("initial@example.org");
givenContact.setPostalAddress("initial postal address");
givenContact.setPhoneNumbers("+01 100 123456789");
}
@Test
void willPatchAllProperties() {
// given
patchResource.setLabel(JsonNullable.of("patched label"));
patchResource.setEmailAddresses(JsonNullable.of("patched@example.org"));
patchResource.setPostalAddress(JsonNullable.of("patched postal address"));
patchResource.setPhoneNumbers(JsonNullable.of("+01 200 987654321"));
// when
hsOfficeContactEntityPatch.apply(patchResource);
// then
new HsOfficeContactEntityMatcher()
.withPatchedLabel("patched label")
.withPatchedEmailAddresses("patched@example.org")
.withPatchedPostalAddress("patched postal address")
.withPatchedPhoneNumbers("+01 200 987654321")
.matches(givenContact);
}
@ParameterizedTest
@ValueSource(strings = { "patched label" })
@NullSource
void willPatchOnlyLabelProperty(final String patchedValue) {
// given
patchResource.setLabel(JsonNullable.of(patchedValue));
// when
hsOfficeContactEntityPatch.apply(patchResource);
// then
new HsOfficeContactEntityMatcher()
.withPatchedLabel(patchedValue)
.matches(givenContact);
}
@ParameterizedTest
@ValueSource(strings = { "patched@example.org" })
@NullSource
void willPatchOnlyEmailAddressesProperty(final String patchedValue) {
// given
patchResource.setEmailAddresses(JsonNullable.of(patchedValue));
// when
hsOfficeContactEntityPatch.apply(patchResource);
// then
new HsOfficeContactEntityMatcher()
.withPatchedEmailAddresses(patchedValue)
.matches(givenContact);
}
@ParameterizedTest
@ValueSource(strings = { "patched postal address" })
@NullSource
void willPatchOnlyPostalAddressProperty(final String patchedValue) {
// given
patchResource.setPostalAddress(JsonNullable.of(patchedValue));
// when
hsOfficeContactEntityPatch.apply(patchResource);
// then
new HsOfficeContactEntityMatcher()
.withPatchedPostalAddress(patchedValue)
.matches(givenContact);
}
@ParameterizedTest
@ValueSource(strings = { "+01 200 987654321" })
@NullSource
void willPatchOnlyPhoneNumbersProperty(final String patchedValue) {
// given
patchResource.setPhoneNumbers(JsonNullable.of(patchedValue));
// when
hsOfficeContactEntityPatch.apply(patchResource);
// then
new HsOfficeContactEntityMatcher()
.withPatchedPhoneNumbers(patchedValue)
.matches(givenContact);
}
private static class HsOfficeContactEntityMatcher {
private String expectedLabel = "initial label";
private String expectedEmailAddresses = "initial@example.org";
private String expectedPostalAddress = "initial postal address";
private String expectedPhoneNumbers = "+01 100 123456789";
HsOfficeContactEntityMatcher withPatchedLabel(final String patchedLabel) {
expectedLabel = patchedLabel;
return this;
}
HsOfficeContactEntityMatcher withPatchedEmailAddresses(final String patchedEmailAddresses) {
expectedEmailAddresses = patchedEmailAddresses;
return this;
}
HsOfficeContactEntityMatcher withPatchedPostalAddress(final String patchedPostalAddress) {
expectedPostalAddress = patchedPostalAddress;
return this;
}
HsOfficeContactEntityMatcher withPatchedPhoneNumbers(final String patchedPhoneNumbers) {
expectedPhoneNumbers = patchedPhoneNumbers;
return this;
}
void matches(final HsOfficeContactEntity givenContact) {
assertThat(givenContact.getLabel()).isEqualTo(expectedLabel);
assertThat(givenContact.getEmailAddresses()).isEqualTo(expectedEmailAddresses);
assertThat(givenContact.getPostalAddress()).isEqualTo(expectedPostalAddress);
assertThat(givenContact.getPhoneNumbers()).isEqualTo(expectedPhoneNumbers);
}
}
}

View File

@ -0,0 +1,66 @@
package net.hostsharing.hsadminng.hs.office.contact;
import net.hostsharing.hsadminng.PatchUnitTestBase;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactPatchResource;
import org.junit.jupiter.api.TestInstance;
import java.util.UUID;
import java.util.stream.Stream;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
@TestInstance(PER_CLASS)
class HsOfficeContactEntityPatcherUnitTest extends PatchUnitTestBase<
HsOfficeContactPatchResource,
HsOfficeContactEntity
> {
private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID();
@Override
protected HsOfficeContactEntity newInitialEntity() {
final var entity = new HsOfficeContactEntity();
entity.setUuid(INITIAL_CONTACT_UUID);
entity.setLabel("initial label");
entity.setEmailAddresses("initial@example.org");
entity.setPhoneNumbers("initial postal address");
entity.setPostalAddress("+01 100 123456789");
return entity;
}
@Override
protected HsOfficeContactPatchResource newPatchResource() {
return new HsOfficeContactPatchResource();
}
@Override
protected HsOfficeContactEntityPatch createPatcher(final HsOfficeContactEntity entity) {
return new HsOfficeContactEntityPatch(entity);
}
@Override
protected Stream<Property> propertyTestDescriptors() {
return Stream.of(
new JsonNullableProperty<>(
"label",
HsOfficeContactPatchResource::setLabel,
"patched label",
HsOfficeContactEntity::setLabel),
new JsonNullableProperty<>(
"emailAddresses",
HsOfficeContactPatchResource::setEmailAddresses,
"patched trade name",
HsOfficeContactEntity::setEmailAddresses),
new JsonNullableProperty<>(
"phoneNumbers",
HsOfficeContactPatchResource::setPhoneNumbers,
"patched family name",
HsOfficeContactEntity::setPhoneNumbers),
new JsonNullableProperty<>(
"patched given name",
HsOfficeContactPatchResource::setPostalAddress,
"patched given name",
HsOfficeContactEntity::setPostalAddress)
);
}
}

View File

@ -14,7 +14,7 @@ import java.util.stream.Stream;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
@TestInstance(PER_CLASS) @TestInstance(PER_CLASS)
class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase< class HsOfficePartnerEntityPatcherUnitTest extends PatchUnitTestBase<
HsOfficePartnerPatchResource, HsOfficePartnerPatchResource,
HsOfficePartnerEntity HsOfficePartnerEntity
> { > {
@ -58,8 +58,8 @@ class HsOfficePartnerEntityPatchUnitTest extends PatchUnitTestBase<
} }
@Override @Override
protected HsOfficePartnerEntityPatch createPatcher(final HsOfficePartnerEntity partner) { protected HsOfficePartnerEntityPatcher createPatcher(final HsOfficePartnerEntity partner) {
return new HsOfficePartnerEntityPatch( return new HsOfficePartnerEntityPatcher(
partner, partner,
uuid -> uuid == PATCHED_CONTACT_UUID uuid -> uuid == PATCHED_CONTACT_UUID
? Optional.of(newContact(uuid)) ? Optional.of(newContact(uuid))

View File

@ -11,7 +11,7 @@ import java.util.stream.Stream;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
@TestInstance(PER_CLASS) @TestInstance(PER_CLASS)
class HsOfficePersonEntityPatchUnitTest extends PatchUnitTestBase< class HsOfficePersonEntityPatcherUnitTest extends PatchUnitTestBase<
HsOfficePersonPatchResource, HsOfficePersonPatchResource,
HsOfficePersonEntity HsOfficePersonEntity
> { > {
@ -35,8 +35,8 @@ class HsOfficePersonEntityPatchUnitTest extends PatchUnitTestBase<
} }
@Override @Override
protected HsOfficePersonEntityPatch createPatcher(final HsOfficePersonEntity entity) { protected HsOfficePersonEntityPatcher createPatcher(final HsOfficePersonEntity entity) {
return new HsOfficePersonEntityPatch(entity); return new HsOfficePersonEntityPatcher(entity);
} }
@Override @Override
@ -66,5 +66,4 @@ class HsOfficePersonEntityPatchUnitTest extends PatchUnitTestBase<
HsOfficePersonEntity::setGivenName) HsOfficePersonEntity::setGivenName)
); );
} }
} }