Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.lang.reflect.Field;
import com.java.pojo.internal.assertion.AbstractAssertionError;

class GetterAssertionError extends AbstractAssertionError {
public class GetterAssertionError extends AbstractAssertionError {

private static final String CONSTRAINT_GETTER = "The getter method for field '%s' should return field value.\n"
+ "Current implementation returns different value.\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,30 @@ public Object generateSameInstance(final Object object) {
return newInstance;
}

/**
* Creates a new instance of {@code clazz} that is guaranteed to be unique relative to other
* instances created for the same type by applying {@code increaseValue} {@code uniquenessIndex}
* times. This prevents false positives in getter tests when a POJO has multiple fields of the
* same type (e.g. two {@code String} fields).
*/
public Object createUniqueInstance(final Class<?> clazz, final int uniquenessIndex) {
Object value = createNewInstance(clazz);
for (int i = 0; i < uniquenessIndex && value != null; i++) {
try {
final Object increased = abstractFieldValueChanger.increaseValue(value);
if (increased == null) {
break;
}
value = increased;
} catch (final ClassCastException e) {
// A value changer mis-matched this type (pre-existing canChange bug);
// stop increasing and use the value we have.
break;
}
}
return value;
}

public List<Object> generateDifferentObjects(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair,
final ClassAndFieldPredicatePair... classAndFieldPredicatePairs) {
return generateDifferentObjects(0,
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/com/java/pojo/internal/tester/GetterTester.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.java.pojo.internal.tester;


import com.java.pojo.api.ClassAndFieldPredicatePair;
import com.java.pojo.internal.field.AbstractFieldValueChanger;
import com.java.pojo.internal.utils.FieldUtils;
Expand All @@ -10,6 +9,7 @@
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class GetterTester extends AbstractTester {

Expand All @@ -30,12 +30,17 @@ public void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair
final List<GetterAndFieldPair> getterAndFieldPairs = findGettersForFields(testedClass, fields);
final Object instance = objectGenerator.createNewInstance(testedClass);

getterAndFieldPairs.forEach(eachPair -> testGetter(eachPair, instance));
IntStream.range(0, getterAndFieldPairs.size()).forEach(i -> testGetter(getterAndFieldPairs.get(i), instance, i));
}

private void testGetter(final GetterAndFieldPair eachPair, final Object instance) {
private void testGetter(final GetterAndFieldPair eachPair, final Object instance, final int fieldIndex)) {
final Method getter = eachPair.getGetter();
final Field field = eachPair.getField();
// Set a unique value for this field before invoking the getter. Using fieldIndex to
// differentiate fields of the same type (e.g. two String fields), which prevents false
// positives caused by copy-paste getter errors returning the wrong field.
final Object uniqueValue = objectGenerator.createUniqueInstance(field.getType(), fieldIndex);
FieldUtils.setValue(instance, field, uniqueValue);
testAssertions.assertThatGetMethodFor(instance)
.willGetValueFromField(getter, field);
}
Expand Down
13 changes: 13 additions & 0 deletions src/test/java/com/java/pojo/internal/tester/GetterTesterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.java.pojo.api.FieldPredicate;
import com.java.pojo.internal.field.DefaultFieldValueChanger;
import com.java.pojo.internal.utils.GetterNotFoundException;
import com.java.pojo.internal.assertion.getter.GetterAssertionError;

import java.util.List;

Expand Down Expand Up @@ -56,6 +57,18 @@ void Should_Pass_All_Getter_Tests_Including_Fields() {
assertThat(result).isNull();
}

@Test
void Should_Fail_When_Getter_Returns_Wrong_Field_Of_Same_Type() {
// given - a POJO with a copy-paste getter bug: getFieldB() returns fieldA
final GetterTester getterTester = new GetterTester(DefaultFieldValueChanger.INSTANCE);

// when
final Throwable result = catchThrowable(() -> getterTester.testAll(CopyPasteGetterBugPojo.class));

// then - the tester must detect the wrong getter
assertThat(result).isInstanceOf(GetterAssertionError.class);
}

@Test
void Should_Fail_Multiple_Classes() {
// given
Expand Down
Loading