Skip to content

Commit

Permalink
#68 - API implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Piotr Joński committed Sep 8, 2016
1 parent b5ca2c7 commit 4e0bd87
Show file tree
Hide file tree
Showing 19 changed files with 707 additions and 53 deletions.
55 changes: 55 additions & 0 deletions src/main/java/org/pojo/tester/AbstractAssetion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.pojo.tester;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.pojo.tester.field.AbstractFieldValueChanger;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class AbstractAssetion {

private static final Set<AbstractTester> DEFAULT_TESTERS;

static {
DEFAULT_TESTERS = new HashSet<>();
Arrays.stream(Method.values())
.map(Method::getTester)
.forEach(DEFAULT_TESTERS::add);
}

Set<AbstractTester> testers = new HashSet<>();
private AbstractFieldValueChanger abstractFieldValueChanger;

public AbstractAssetion using(final AbstractFieldValueChanger abstractFieldValueChanger) {
this.abstractFieldValueChanger = abstractFieldValueChanger;
return this;
}

public AbstractAssetion testing(final Method... methods) {
Arrays.asList(methods)
.forEach(this::testing);
return this;
}

public AbstractAssetion testing(final Method method) {
final AbstractTester tester = method.getTester();
this.testers.add(tester);
return this;
}

public void areWellImplemented() {
if (testers.isEmpty()) {
testers = DEFAULT_TESTERS;
}
if (abstractFieldValueChanger != null) {
testers.forEach(tester -> tester.setFieldValuesChanger(abstractFieldValueChanger));
}

testImplementation();
}

protected abstract void testImplementation();

}
33 changes: 31 additions & 2 deletions src/main/java/org/pojo/tester/AbstractTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.pojo.tester.assertion.Assertions;
import org.pojo.tester.field.AbstractFieldValueChanger;
import org.pojo.tester.field.DefaultFieldValueChanger;
Expand All @@ -11,8 +13,8 @@

public abstract class AbstractTester {

protected final Assertions assertions = new Assertions();
protected final ObjectGenerator objectGenerator;
protected ObjectGenerator objectGenerator;
protected Assertions assertions = new Assertions();

public AbstractTester() {
this(DefaultFieldValueChanger.INSTANCE);
Expand Down Expand Up @@ -47,4 +49,31 @@ public void testAll(final ClassAndFieldPredicatePair... classesAndFieldPredicate

public abstract void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, final ClassAndFieldPredicatePair... classAndFieldPredicatePairs);

public void setFieldValuesChanger(final AbstractFieldValueChanger fieldValuesChanger) {
objectGenerator = new ObjectGenerator(fieldValuesChanger);
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {
return false;
}

final AbstractTester that = (AbstractTester) o;

return new EqualsBuilder().append(objectGenerator, that.objectGenerator)
.append(assertions, that.assertions)
.isEquals();
}

@Override
public int hashCode() {
return new HashCodeBuilder().append(objectGenerator)
.append(assertions)
.toHashCode();
}
}
41 changes: 41 additions & 0 deletions src/main/java/org/pojo/tester/Assetions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.pojo.tester;


import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;


@AllArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class Assetions {

public static AbstractAssetion assertPojoMethodsFor(final Class<?> clazz) {
final Predicate<String> predicateAcceptingAllFields = FieldPredicate.includeAllFields(clazz);
return assertPojoMethodsFor(clazz, predicateAcceptingAllFields);
}

public static AbstractAssetion assertPojoMethodsFor(final Class<?> clazz, final Predicate<String> fieldPredicate) {
final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair(clazz, fieldPredicate);
return assertPojoMethodsFor(classAndFieldPredicatePair);
}

public static AbstractAssetion assertPojoMethodsFor(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair,
final ClassAndFieldPredicatePair... classAndFieldPredicatePairs) {
return new SingleClassAssetion(baseClassAndFieldPredicatePair, classAndFieldPredicatePairs);
}

public static AbstractAssetion assertPojoMethodsForAll(final Class... classes) {
final ClassAndFieldPredicatePair[] classesAndFieldPredicatesPairs = Arrays.stream(classes)
.map(ClassAndFieldPredicatePair::new)
.toArray(ClassAndFieldPredicatePair[]::new);
return assertPojoMethodsForAll(classesAndFieldPredicatesPairs);
}

public static AbstractAssetion assertPojoMethodsForAll(final ClassAndFieldPredicatePair... classesAndFieldPredicatesPairs) {
final List<ClassAndFieldPredicatePair> classAndFieldPredicatePairs = Arrays.asList(classesAndFieldPredicatesPairs);
return new MultiClassAssetion(classAndFieldPredicatePairs);
}

}
17 changes: 17 additions & 0 deletions src/main/java/org/pojo/tester/Method.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.pojo.tester;

import lombok.Getter;

@Getter
public enum Method {
EQUALS(new EqualsTester()),
HASH_CODE(new HashCodeTester()),
SETTERS_AND_GETTERS(new SetterGetterTester()),
TO_STRING(new ToStringTester());

private final AbstractTester tester;

Method(final AbstractTester tester) {
this.tester = tester;
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/pojo/tester/MultiClassAssetion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.pojo.tester;

import java.util.List;

class MultiClassAssetion extends AbstractAssetion {

private final List<ClassAndFieldPredicatePair> classAndFieldPredicatePairs;

MultiClassAssetion(final List<ClassAndFieldPredicatePair> classAndFieldPredicatePairs) {
this.classAndFieldPredicatePairs = classAndFieldPredicatePairs;
}

@Override
public void testImplementation() {
final ClassAndFieldPredicatePair[] classes = classAndFieldPredicatePairs.toArray(new ClassAndFieldPredicatePair[classAndFieldPredicatePairs.size()]);
testers.forEach(tester -> tester.testAll(classes));
}
}
15 changes: 12 additions & 3 deletions src/main/java/org/pojo/tester/SetterGetterTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,32 @@ private void testSetterAndGetter(final SetterAndGetterPair eachPair, final Objec
final Object newValue = objectGenerator.createNewInstance(fieldType);

try {
assertions.assertThatSetMethodFor(instance)
.willSetValueOnField(setter, field, newValue);
if (setter != null) {
assertions.assertThatSetMethodFor(instance)
.willSetValueOnField(setter, field, newValue);
}
assertions.assertThatGetMethodFor(instance)
.willGetValueFromField(getter, field);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new GetOrSetValueException(field.getName(), instance.getClass(), e);
}
}

private boolean isNotFinal(final Field field) {
return !FieldUtils.isFinal(field);
}

private List<SetterAndGetterPair> findSetterAndGetterPairsForFields(final Class<?> testedClass, final List<Field> fields) {
return fields.stream()
.map(fieldName -> findSetterAndGetterPairForField(testedClass, fieldName))
.collect(Collectors.toList());
}

private SetterAndGetterPair findSetterAndGetterPairForField(final Class<?> testedClass, final Field field) {
final Method setter = MethodUtils.findSetterFor(testedClass, field);
Method setter = null;
if (isNotFinal(field)) {
setter = MethodUtils.findSetterFor(testedClass, field);
}
final Method getter = MethodUtils.findGetterFor(testedClass, field);
return new SetterAndGetterPair(setter, getter, field);
}
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/pojo/tester/SingleClassAssetion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.pojo.tester;

class SingleClassAssetion extends AbstractAssetion {

private final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair;
private final ClassAndFieldPredicatePair[] classAndFieldPredicatePairs;

SingleClassAssetion(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, final ClassAndFieldPredicatePair[] classAndFieldPredicatePairs) {
this.baseClassAndFieldPredicatePair = baseClassAndFieldPredicatePair;
this.classAndFieldPredicatePairs = classAndFieldPredicatePairs;
}

@Override
public void testImplementation() {
testers.forEach(tester -> tester.test(baseClassAndFieldPredicatePair, classAndFieldPredicatePairs));
}
}
24 changes: 12 additions & 12 deletions src/main/java/org/pojo/tester/instantiator/ObjectGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,22 @@ public List<Object> generateDifferentObjects(final ClassAndFieldPredicatePair ba
final Object newFieldTypeInstance = createNewInstance(permutationFieldType);
FieldUtils.setValue(baseObjectCopy, permutationField, newFieldTypeInstance);
} else {
final List<Object> childs;
final List<Object> nestedObjectsOfFieldType;
if (dejaVu.containsKey(permutationFieldType)) {
childs = new ArrayList<>(dejaVu.get(permutationFieldType));
nestedObjectsOfFieldType = new ArrayList<>(dejaVu.get(permutationFieldType));
} else {
final Predicate<String> fieldPredicate = userDefinedClassAndFieldPredicatePairsMap.get(permutationFieldType);
final List<Field> fieldClassFields = FieldUtils.getFields(permutationFieldType, fieldPredicate);

if (hasNestedFieldsToChange(fieldClassFields, userDefinedClassAndFieldPredicatePairsMap)) {
final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair(permutationFieldType, fieldPredicate);
childs = generateDifferentObjects(classAndFieldPredicatePair, classAndFieldPredicatePairs);
nestedObjectsOfFieldType = generateDifferentObjects(classAndFieldPredicatePair, classAndFieldPredicatePairs);
} else {
childs = generateDifferentObjects(permutationFieldType, fieldClassFields);
nestedObjectsOfFieldType = generateDifferentObjects(permutationFieldType, fieldClassFields);
}
dejaVu.putIfAbsent(permutationFieldType, childs);
dejaVu.putIfAbsent(permutationFieldType, nestedObjectsOfFieldType);
}
nestedObjectsThatAreWaitingForSetInBaseObjectCopy.put(permutationField, childs);
nestedObjectsThatAreWaitingForSetInBaseObjectCopy.put(permutationField, nestedObjectsOfFieldType);
}
}

Expand All @@ -108,15 +108,15 @@ Object generateInstanceWithDifferentFieldValues(final Object baseObject, final L
}

private List<Object> generateDifferentObjects(final Class<?> clazz, final List<Field> fieldsToChange) {
final List<Object> childs;
final List<Object> differentObjects;
final List<List<Field>> permutationOfFields = FieldUtils.permutations(fieldsToChange);
final Object fieldObject = createNewInstance(clazz);

childs = permutationOfFields.stream()
.map(fields -> generateInstanceWithDifferentFieldValues(fieldObject, fields))
.collect(Collectors.toList());
childs.add(0, fieldObject);
return childs;
differentObjects = permutationOfFields.stream()
.map(fields -> generateInstanceWithDifferentFieldValues(fieldObject, fields))
.collect(Collectors.toList());
differentObjects.add(0, fieldObject);
return differentObjects;
}

private List<Object> createCopiesAndFillThem(final List<Object> baseObjects, final Map.Entry<Field, List<Object>> nestedObjectsToSet) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/org/pojo/tester/utils/FieldUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public static List<Field> getFields(final Class<?> testedClass, final Predicate<
.collect(Collectors.toList());
}

public static boolean isFinal(final Field field) {
final int fieldModifiers = field.getModifiers();
return Modifier.isFinal(fieldModifiers);
}

static List<Field> getSpecifiedFields(final Class<?> clazz, final List<String> names) {
return names.stream()
.map(name -> getField(clazz, name))
Expand Down Expand Up @@ -105,6 +110,4 @@ private static Field getField(final Class<?> clazz, final String name) {
throw new GetOrSetValueException(name, clazz, e);
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package matchers;

import org.mockito.ArgumentMatcher;
import org.pojo.tester.ClassAndFieldPredicatePair;

public class ClassAndFieldPredicatePairArgumentMatcher extends ArgumentMatcher<ClassAndFieldPredicatePair> {
private final Class<?> clazz;
private final String fieldName;

public ClassAndFieldPredicatePairArgumentMatcher(final Class<?> clazz, final String fieldName) {
this.clazz = clazz;
this.fieldName = fieldName;
}

@Override
public boolean matches(final Object argument) {
final ClassAndFieldPredicatePair classAndFieldPredicatePair = (ClassAndFieldPredicatePair) argument;

final boolean classesMatches = classAndFieldPredicatePair.getClazz()
.equals(clazz);

final boolean predicateMatches = classAndFieldPredicatePair.getFieldsPredicate()
.test(fieldName);
return classesMatches && predicateMatches;
}
}
21 changes: 21 additions & 0 deletions src/test/java/matchers/RecursivelyEqualArgumentMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package matchers;

import org.mockito.ArgumentMatcher;
import org.pojo.tester.ClassAndFieldPredicatePair;

import static org.assertj.core.api.Assertions.assertThat;

public class RecursivelyEqualArgumentMatcher extends ArgumentMatcher<ClassAndFieldPredicatePair> {
private final ClassAndFieldPredicatePair expectedParameter;

public RecursivelyEqualArgumentMatcher(final ClassAndFieldPredicatePair expectedParameter) {
this.expectedParameter = expectedParameter;
}

@Override
public boolean matches(final Object argument) {
final ClassAndFieldPredicatePair classAndFieldPredicatePair = (ClassAndFieldPredicatePair) argument;
assertThat(classAndFieldPredicatePair).isEqualToComparingFieldByFieldRecursively(expectedParameter);
return true;
}
}
13 changes: 13 additions & 0 deletions src/test/java/matchers/StringPredicateArgumentMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package matchers;

import java.util.function.Predicate;
import org.mockito.ArgumentMatcher;

public class StringPredicateArgumentMatcher extends ArgumentMatcher<Predicate<String>> {

@Override
public boolean matches(final Object argument) {
final Predicate<String> stringPredicate = (Predicate<String>) argument;
return stringPredicate.test("a");
}
}

0 comments on commit 4e0bd87

Please sign in to comment.