From 259a6760a967cbd152b79d3f53c4c38d40559f55 Mon Sep 17 00:00:00 2001 From: Miguel Reboiro-Jato Date: Tue, 18 Oct 2016 11:37:03 +0200 Subject: [PATCH] Improves the IsEqualToEntity abstract matcher The IsEqualToEntity matcher (previously, IsEqualsToEntity) has been improved to allow property comparison by functional reference to the getter methods of the properties to compare. Specifically, the "checkAttribute" methods added allow providing a Function as a getter, where T is the type of the entity to compare and R is the type returned by the getter method. --- .../esei/xcs/rest/OwnerResourceRestTest.java | 8 +- .../esei/xcs/rest/OwnerResourceUnitTest.java | 6 +- .../service/OwnerServiceIntegrationTest.java | 18 +- .../service/PetServiceIntegrationTest.java | 6 +- .../xcs/domain/entities/IsEqualToEntity.java | 363 ++++++++++++++++++ .../xcs/domain/entities/IsEqualToOwner.java | 57 +++ .../xcs/domain/entities/IsEqualToPet.java | 59 +++ .../xcs/domain/entities/IsEqualsToEntity.java | 56 --- .../xcs/domain/entities/IsEqualsToOwner.java | 65 ---- .../xcs/domain/entities/IsEqualsToPet.java | 68 ---- 10 files changed, 498 insertions(+), 208 deletions(-) create mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToEntity.java create mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToOwner.java create mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToPet.java delete mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java delete mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java delete mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java index db7a4b0..9a44eda 100644 --- a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java @@ -1,7 +1,7 @@ package es.uvigo.esei.xcs.rest; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.containsOwnersInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.equalToOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.EXISTENT_LOGIN; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.NON_EXISTENT_LOGIN; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.OWNER_WITHOUT_PETS_LOGIN; @@ -89,7 +89,7 @@ public class OwnerResourceRestTest { final Owner owner = response.readEntity(Owner.class); final Owner expected = existentOwner(); - assertThat(owner, is(equalsToOwner(expected))); + assertThat(owner, is(equalToOwner(expected))); } @Test @InSequence(3) @@ -202,7 +202,7 @@ public class OwnerResourceRestTest { final Response responseGet = authorizedJsonRequestGet(location); final Owner owner = responseGet.readEntity(Owner.class); - assertThat(owner, is(equalsToOwner(persistentOwner))); + assertThat(owner, is(equalToOwner(persistentOwner))); } diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java index baa5c4a..7902692 100644 --- a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java @@ -1,7 +1,7 @@ package es.uvigo.esei.xcs.rest; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.containsOwnersInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.equalToOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyLogin; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentOwner; @@ -73,7 +73,7 @@ public class OwnerResourceUnitTest extends EasyMockSupport { assertThat(response, hasHttpStatus(OK)); assertThat(response.getEntity(), is(instanceOf(Owner.class))); - assertThat((Owner) response.getEntity(), is(equalsToOwner(owner))); + assertThat((Owner) response.getEntity(), is(equalToOwner(owner))); } @Test(expected = IllegalArgumentException.class) diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java index d62aeae..f197e79 100644 --- a/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java +++ b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java @@ -1,8 +1,8 @@ package es.uvigo.esei.xcs.service; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.containsPetsInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.containsOwnersInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.equalToOwner; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToPet.containsPetsInAnyOrder; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentLogin; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets; @@ -77,7 +77,7 @@ public class OwnerServiceIntegrationTest { final Owner actual = asAdmin.call(() -> facade.get(login)); - assertThat(actual, is(equalsToOwner(ownerWithLogin(login)))); + assertThat(actual, is(equalToOwner(ownerWithLogin(login)))); } @Test @@ -113,7 +113,7 @@ public class OwnerServiceIntegrationTest { final List owners = asAdmin.call(() -> facade.findByPetName(petName)); assertThat(owners, hasSize(1)); - assertThat(owners.get(0), is(equalsToOwner(owner))); + assertThat(owners.get(0), is(equalToOwner(owner))); } @Test @@ -151,7 +151,7 @@ public class OwnerServiceIntegrationTest { final Owner actual = asAdmin.call(() -> facade.create(newOwner)); - assertThat(actual, is(equalsToOwner(newOwner))); + assertThat(actual, is(equalToOwner(newOwner))); } @Test @@ -159,7 +159,7 @@ public class OwnerServiceIntegrationTest { public void testCreateWithPets() { final Owner actual = asAdmin.call(() -> facade.create(newOwnerWithFreshPets())); - assertThat(actual, is(equalsToOwner(newOwnerWithPersistentPets()))); + assertThat(actual, is(equalToOwner(newOwnerWithPersistentPets()))); } @Test(expected = EJBTransactionRolledbackException.class) @@ -196,7 +196,7 @@ public class OwnerServiceIntegrationTest { final Owner actual = asAdmin.call(() -> facade.update(newOwner)); - assertThat(actual, is(equalsToOwner(newOwner))); + assertThat(actual, is(equalToOwner(newOwner))); } @Test @@ -204,7 +204,7 @@ public class OwnerServiceIntegrationTest { public void testUpdateNewOwnerWithPets() { final Owner actual = asAdmin.call(() -> facade.update(newOwnerWithFreshPets())); - assertThat(actual, is(equalsToOwner(newOwnerWithPersistentPets()))); + assertThat(actual, is(equalToOwner(newOwnerWithPersistentPets()))); } @Test diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java index 3d7c94b..79bc89d 100644 --- a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java +++ b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java @@ -1,7 +1,7 @@ package es.uvigo.esei.xcs.service; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.containsPetsInAnyOrder; -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.equalsToPet; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToPet.containsPetsInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualToPet.equalToPet; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentPetId; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPet; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPetWithOwner; @@ -75,7 +75,7 @@ public class PetServiceIntegrationTest { final Pet actual = asOwner.call(() -> facade.get(id)); - assertThat(actual, equalsToPet(pet)); + assertThat(actual, equalToPet(pet)); } @Test diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToEntity.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToEntity.java new file mode 100644 index 0000000..704730f --- /dev/null +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToEntity.java @@ -0,0 +1,363 @@ +package es.uvigo.esei.xcs.domain.entities; + +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.StreamSupport; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +/** + * An abstract {@link Matcher} that can be used to create new matchers that + * compare entities by their attributes. + * + * @author Miguel Reboiro Jato + * + * @param the type of the entities to be matched. + */ +public abstract class IsEqualToEntity extends TypeSafeMatcher { + /** + * The expected entity. + */ + protected final T expected; + + private Consumer describeTo; + + /** + * Constructs a new instance of {@link IsEqualToEntity}. + * + * @param entity the expected tentity. + */ + public IsEqualToEntity(final T entity) { + this.expected = requireNonNull(entity); + } + + @Override + public void describeTo(final Description description) { + if (this.describeTo != null) + this.describeTo.accept(description); + } + + /** + * Adds a new description using the template: + *

+ * {@code entity with value '' for } + *

+ * + * @param attribute the name of the attribute compared. + * @param expected the expected value. + */ + protected void addTemplatedDescription(final String attribute, final Object expected) { + this.describeTo = d -> d.appendText(String.format( + "%s entity with value '%s' for %s", + this.expected.getClass().getSimpleName(), + expected, attribute + )); + } + + /** + * Adds as the description of this matcher the + * {@link Matcher#describeTo(Description)} method of other matcher. + * + * @param matcher the matcher whose description will be used. + */ + protected void addMatcherDescription(final Matcher matcher) { + this.describeTo = matcher::describeTo; + } + + /** + * Cleans the current description. + */ + protected void clearDescribeTo() { + this.describeTo = null; + } + + protected boolean checkAttribute( + final String attribute, + final Function getter, final T actual, + final Function> matcherFactory + ) { + final R expectedValue = getter.apply(this.expected); + final R actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || actualValue == null) { + this.addTemplatedDescription(attribute, expectedValue); + return false; + } else { + final Matcher matcher = matcherFactory.apply(expectedValue); + if (matcher.matches(actualValue)) { + return true; + } else { + this.addMatcherDescription(matcher); + + return false; + } + } + } + + /** + * Compares the expected and the actual value of an array attribute. The + * elements of the attribute will be checked using a custom matcher. + * If the comparison fails, the description of the error will be updated. + * + * @param attribute the name of the attribute compared. + * @param getter the getter function of the attribute. + * @param actual the actual entity being compared to the expected entity. + * @param matcherFactory a function that creates a matcher for the expected + * array values. + * @param type of the value returned by the getter. + * @return {@code true} if the value of the expected and actual attributes + * are equals and {@code false} otherwise. If the result is {@code false}, + * the current description will be updated. + */ + protected boolean checkArrayAttribute( + final String attribute, + final Function getter, final T actual, + final Function>> matcherFactory + ) { + final R[] expectedValue = getter.apply(this.expected); + final R[] actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || actualValue == null) { + this.addTemplatedDescription(attribute, expectedValue); + return false; + } else { + final Matcher> matcher = + matcherFactory.apply(expectedValue); + + if (matcher.matches(asList(actualValue))) { + return true; + } else { + this.addMatcherDescription(matcher); + + return false; + } + } + } + + /** + * Compares the expected and the actual value of an iterable attribute. The + * elements of the attribute will be checked using a custom matcher. + * If the comparison fails, the description of the error will be updated. + * + * @param attribute the name of the attribute compared. + * @param getter the getter function of the attribute. + * @param actual the actual entity being compared to the expected entity. + * @param matcherFactory a function that creates a matcher for the expected + * iterable values. + * @param type of the value returned by the getter. + * @return {@code true} if the value of the expected and actual attributes + * are equals and {@code false} otherwise. If the result is {@code false}, + * the current description will be updated. + */ + protected boolean checkIterableAttribute( + final String attribute, + final Function> getter, final T actual, + final Function, Matcher>> matcherFactory + ) { + final Iterable expectedValue = getter.apply(this.expected); + final Iterable actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || actualValue == null) { + this.addTemplatedDescription(attribute, expectedValue); + return false; + } else { + final Matcher> matcher = + matcherFactory.apply(expectedValue); + + if (matcher.matches(actualValue)) { + return true; + } else { + this.addMatcherDescription(matcher); + + return false; + } + } + } + + /** + * Compares the expected and the actual value of an attribute. If the + * comparison fails, the description of the error will be updated. + * + * @param attribute the name of the attribute compared. + * @param getter the getter function of the attribute. + * @param actual the actual entity being compared to the expected entity. + * @param type of the value returned by the getter. + * @return {@code true} if the value of the expected and actual attributes + * are equals and {@code false} otherwise. If the result is {@code false}, + * the current description will be updated. + */ + protected boolean checkAttribute( + final String attribute, final Function getter, final T actual + ) { + final R expectedValue = getter.apply(this.expected); + final R actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || !expectedValue.equals(actualValue)) { + this.addTemplatedDescription(attribute, expectedValue); + return false; + } else { + return true; + } + } + + /** + * Compares the expected and the actual value of an array attribute. If the + * comparison fails, the description of the error will be updated. + * + * @param attribute the name of the attribute compared. + * @param getter the getter function of the attribute. + * @param actual the actual entity being compared to the expected entity. + * @param type of the value returned by the getter. + * @return {@code true} if the value of the expected and actual attributes + * are equals and {@code false} otherwise. If the result is {@code false}, + * the current description will be updated. + */ + protected boolean checkArrayAttribute( + final String attribute, final Function getter, final T actual + ) { + final R[] expectedValue = getter.apply(this.expected); + final R[] actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || actualValue == null) { + this.addTemplatedDescription(attribute, expectedValue == null ? "null" : Arrays.toString(expectedValue)); + return false; + } else if (!Arrays.equals(expectedValue, actualValue)) { + this.addTemplatedDescription(attribute, Arrays.toString(expectedValue)); + return false; + } else + return true; + } + + /** + * Compares the expected and the actual value of an int array attribute. If + * the comparison fails, the description of the error will be updated. + * + * @param attribute the name of the attribute compared. + * @param getter the getter function of the attribute. + * @param actual the actual entity being compared to the expected entity. + * @return {@code true} if the value of the expected and actual attributes + * are equals and {@code false} otherwise. If the result is {@code false}, + * the current description will be updated. + */ + protected boolean checkIntArrayAttribute( + final String attribute, final Function getter, final T actual + ) { + final int[] expectedValue = getter.apply(this.expected); + final int[] actualValue = getter.apply(actual); + + if (expectedValue == null && actualValue == null) { + return true; + } else if (expectedValue == null || actualValue == null) { + this.addTemplatedDescription(attribute, expectedValue == null ? "null" : Arrays.toString(expectedValue)); + return false; + } else if (!Arrays.equals(expectedValue, actualValue)) { + this.addTemplatedDescription(attribute, Arrays.toString(expectedValue)); + return false; + } else + return true; + } + + /** + * Utility method that generates a {@link Matcher} that compares several + * entities. + * + * @param converter a function to create a matcher for an entity. + * @param entities the entities to be used as the expected values. + * @param type of the entity. + * @return a new {@link Matcher} that compares several entities. + */ + @SafeVarargs + protected static Matcher> containsEntityInAnyOrder( + final Function> converter, final T ... entities + ) { + final Collection> entitiesMatchers = stream(entities) + .map(converter) + .collect(toList()); + + return containsInAnyOrder(entitiesMatchers); + } + + /** + * Utility method that generates a {@link Matcher} that compares several + * entities. + * + * @param converter a function to create a matcher for an entity. + * @param entities the entities to be used as the expected values. + * @param type of the entity. + * @return a new {@link Matcher} that compares several entities. + */ + protected static Matcher> containsEntityInAnyOrder( + final Function> converter, final Iterable entities + ) { + final Collection> entitiesMatchers = + StreamSupport.stream(entities.spliterator(), false) + .map(converter) + .collect(toList()); + + return containsInAnyOrder(entitiesMatchers); + } + + /** + * Utility method that generates a {@link Matcher} that compares several + * entities in the same received order. + * + * @param converter A function to create a matcher for an entity. + * @param entities The entities to be used as the expected values, in the + * order to be compared. + * @param The type of the entity. + * + * @return A new {@link Matcher} that compares several entities in the same + * received order. + */ + @SafeVarargs + protected static Matcher> containsEntityInOrder( + final Function> converter, final T ... entities + ) { + return contains(stream(entities).map(converter).collect(toList())); + } + + /** + * Utility method that generates a {@link Matcher} that compares several + * entities in the same received order. + * + * @param converter A function to create a matcher for an entity. + * @param entities The entities to be used as the expected values, in the + * order to be compared. + * @param The type of the entity. + * + * @return A new {@link Matcher} that compares several entities in the same + * received order. + */ + protected static Matcher> containsEntityInOrder( + final Function> converter, final Iterable entities + ) { + final List> matchersList = + StreamSupport.stream(entities.spliterator(), false) + .map(converter) + .collect(toList()); + + return contains(matchersList); + } +} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToOwner.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToOwner.java new file mode 100644 index 0000000..848ca78 --- /dev/null +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToOwner.java @@ -0,0 +1,57 @@ +package es.uvigo.esei.xcs.domain.entities; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +public class IsEqualToOwner extends IsEqualToEntity { + private final boolean checkRelations; + + public IsEqualToOwner(Owner owner, boolean checkRelations) { + super(owner); + this.checkRelations = checkRelations; + } + + @Override + protected boolean matchesSafely(Owner actual) { + this.clearDescribeTo(); + + if (actual == null) { + this.addTemplatedDescription("actual", expected.toString()); + return false; + } else { + return checkAttribute("login", Owner::getLogin, actual) + && checkAttribute("password", Owner::getPassword, actual) + && (!this.checkRelations || checkIterableAttribute("pets", Owner::getPets, actual, IsEqualToPet::containsPetsWithoutRelationsInAnyOrder)); + } + } + + @Factory + public static IsEqualToOwner equalToOwner(Owner owner) { + return new IsEqualToOwner(owner, true); + } + + @Factory + public static IsEqualToOwner equalToOwnerWithoutRelations(Owner owner) { + return new IsEqualToOwner(owner, false); + } + + @Factory + public static Matcher> containsOwnersInAnyOrder(Owner ... owners) { + return containsEntityInAnyOrder(IsEqualToOwner::equalToOwner, owners); + } + + @Factory + public static Matcher> containsOwnersWithoutRelationsInAnyOrder(Owner ... owners) { + return containsEntityInAnyOrder(IsEqualToOwner::equalToOwnerWithoutRelations, owners); + } + + @Factory + public static Matcher> containsOwnersInAnyOrder(Iterable owners) { + return containsEntityInAnyOrder(IsEqualToOwner::equalToOwner, owners); + } + + @Factory + public static Matcher> containsOwnersWithoutRelationsInAnyOrder(Iterable owners) { + return containsEntityInAnyOrder(IsEqualToOwner::equalToOwnerWithoutRelations, owners); + } +} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToPet.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToPet.java new file mode 100644 index 0000000..769fc66 --- /dev/null +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToPet.java @@ -0,0 +1,59 @@ +package es.uvigo.esei.xcs.domain.entities; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +public class IsEqualToPet extends IsEqualToEntity { + private final boolean checkRelations; + + public IsEqualToPet(Pet pet, boolean checkRelations) { + super(pet); + this.checkRelations = checkRelations; + } + + @Override + protected boolean matchesSafely(Pet actual) { + this.clearDescribeTo(); + + if (actual == null) { + this.addTemplatedDescription("actual", expected.toString()); + return false; + } else { + return checkAttribute("id", Pet::getId, actual) + && checkAttribute("name", Pet::getName, actual) + && checkAttribute("animal", Pet::getAnimal, actual) + && checkAttribute("birth", Pet::getBirth, actual) + && (!this.checkRelations || checkAttribute("owner", Pet::getOwner, actual, IsEqualToOwner::equalToOwnerWithoutRelations)); + } + } + + @Factory + public static IsEqualToPet equalToPet(Pet pet) { + return new IsEqualToPet(pet, true); + } + + @Factory + public static IsEqualToPet equalToPetWithoutRelations(Pet pet) { + return new IsEqualToPet(pet, false); + } + + @Factory + public static Matcher> containsPetsInAnyOrder(Pet ... pets) { + return containsEntityInAnyOrder(IsEqualToPet::equalToPet, pets); + } + + @Factory + public static Matcher> containsPetsWithoutRelationsInAnyOrder(Pet ... pets) { + return containsEntityInAnyOrder(IsEqualToPet::equalToPetWithoutRelations, pets); + } + + @Factory + public static Matcher> containsPetsInAnyOrder(Iterable pets) { + return containsEntityInAnyOrder(IsEqualToPet::equalToPet, pets); + } + + @Factory + public static Matcher> containsPetsWithoutRelationsInAnyOrder(Iterable pets) { + return containsEntityInAnyOrder(IsEqualToPet::equalToPetWithoutRelations, pets); + } +} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java deleted file mode 100644 index c35be73..0000000 --- a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -package es.uvigo.esei.xcs.domain.entities; - -import static java.util.Arrays.stream; -import static java.util.stream.Collectors.toList; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; - -import java.util.Collection; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -public abstract class IsEqualsToEntity extends TypeSafeMatcher { - protected final T expected; - private Consumer describeTo; - - public IsEqualsToEntity(T entity) { - this.expected = entity; - } - - @Override - public void describeTo(Description description) { - if (this.describeTo != null) { - this.describeTo.accept(description); - } - } - - protected void addTemplatedDescription(String attribute, Object expected) { - this.describeTo = d -> d.appendText(String.format( - "%s entity with value '%s' for %s", - this.expected.getClass().getSimpleName(), - expected, attribute - )); - } - - protected void addMatcherDescription(Matcher matcher) { - this.describeTo = matcher::describeTo; - } - - protected void clearDescribeTo() { - this.describeTo = null; - } - - @SafeVarargs - protected static Matcher> containsEntityInAnyOrder( - Function> converter, T ... entities - ) { - final Collection> ownerMatchers = stream(entities) - .map(converter) - .collect(toList()); - - return containsInAnyOrder(ownerMatchers); - } -} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java deleted file mode 100644 index 96dedc6..0000000 --- a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java +++ /dev/null @@ -1,65 +0,0 @@ -package es.uvigo.esei.xcs.domain.entities; - -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.containsPetsWithoutRelationsInAnyOrder; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -public class IsEqualsToOwner extends IsEqualsToEntity { - private final boolean checkRelations; - - public IsEqualsToOwner(Owner owner, boolean checkRelations) { - super(owner); - this.checkRelations = checkRelations; - } - - @Override - protected boolean matchesSafely(Owner actual) { - this.clearDescribeTo(); - - if (actual == null) { - this.addTemplatedDescription("owner", expected.toString()); - return false; - } else if (!expected.getLogin().equals(actual.getLogin())) { - this.addTemplatedDescription("login", expected.getLogin()); - return false; - } else if (!expected.getPassword().equals(actual.getPassword())) { - this.addTemplatedDescription("password", expected.getPassword()); - return false; - } else if (this.checkRelations) { - final Matcher> petsMatcher = - containsPetsWithoutRelationsInAnyOrder( - expected.getPets().toArray(new Pet[0])); - - if (petsMatcher.matches(actual.getPets())) { - this.addMatcherDescription(petsMatcher); - - return true; - } else { - return false; - } - } else { - return true; - } - } - - @Factory - public static IsEqualsToOwner equalsToOwner(Owner owner) { - return new IsEqualsToOwner(owner, true); - } - - @Factory - public static IsEqualsToOwner equalsToOwnerWithoutRelations(Owner owner) { - return new IsEqualsToOwner(owner, false); - } - - @Factory - public static Matcher> containsOwnersInAnyOrder(Owner ... owners) { - return containsEntityInAnyOrder(IsEqualsToOwner::equalsToOwner, owners); - } - - @Factory - public static Matcher> containsOwnersWithoutRelationsInAnyOrder(Owner ... owners) { - return containsEntityInAnyOrder(IsEqualsToOwner::equalsToOwnerWithoutRelations, owners); - } -} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java deleted file mode 100644 index 50c063e..0000000 --- a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java +++ /dev/null @@ -1,68 +0,0 @@ -package es.uvigo.esei.xcs.domain.entities; - -import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwnerWithoutRelations; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -public class IsEqualsToPet extends IsEqualsToEntity { - private final boolean checkRelations; - - public IsEqualsToPet(Pet pet, boolean checkRelations) { - super(pet); - this.checkRelations = checkRelations; - } - - @Override - protected boolean matchesSafely(Pet actual) { - this.clearDescribeTo(); - - if (actual == null) { - this.addTemplatedDescription("pet", expected.toString()); - return false; - } else if (this.expected.getId() != actual.getId()) { - this.addTemplatedDescription("id", expected.getId()); - return false; - } else if (!this.expected.getName().equals(actual.getName())) { - this.addTemplatedDescription("name", expected.getName()); - return false; - } else if (!this.expected.getAnimal().equals(actual.getAnimal())) { - this.addTemplatedDescription("animal", expected.getAnimal()); - return false; - } else if (this.expected.getBirth().getTime() != actual.getBirth().getTime()) { - this.addTemplatedDescription("birth", expected.getBirth()); - return false; - } else if (this.checkRelations) { - final IsEqualsToOwner equalsToOwner = equalsToOwnerWithoutRelations(this.expected.getOwner()); - - if (equalsToOwner.matchesSafely(actual.getOwner())) { - return true; - } else { - this.addMatcherDescription(equalsToOwner); - return false; - } - } else { - return true; - } - } - - @Factory - public static IsEqualsToPet equalsToPet(Pet pet) { - return new IsEqualsToPet(pet, true); - } - - @Factory - public static IsEqualsToPet equalsToPetWithoutRelations(Pet pet) { - return new IsEqualsToPet(pet, false); - } - - @Factory - public static Matcher> containsPetsInAnyOrder(Pet ... pets) { - return containsEntityInAnyOrder(IsEqualsToPet::equalsToPet, pets); - } - - @Factory - public static Matcher> containsPetsWithoutRelationsInAnyOrder(Pet ... pets) { - return containsEntityInAnyOrder(IsEqualsToPet::equalsToPetWithoutRelations, pets); - } -} -- 2.18.1