Skip to content

Commit

Permalink
Enable custom matching on inherited fields
Browse files Browse the repository at this point in the history
Fixes shazam#15.
  • Loading branch information
nieldw committed Aug 8, 2017
1 parent 684117f commit 87f9172
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 4 deletions.
34 changes: 30 additions & 4 deletions src/main/java/com/shazam/shazamcrest/BeanFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
*/
package com.shazam.shazamcrest;

import static java.util.Arrays.asList;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

import static java.lang.reflect.Modifier.isProtected;
import static java.lang.reflect.Modifier.isPublic;
import static java.util.Arrays.asList;

/**
* Returns the object corresponding to the path specified
*/
Expand All @@ -30,7 +33,7 @@ public static Object findBeanAt(String fieldPath, Object object) {
}

private static Object findBeanAt(List<String> fields, Object object) {
for (Field field : object.getClass().getDeclaredFields()) {
for (Field field : getAllFields(object.getClass())) {
field.setAccessible(true);
if (headOf(fields).equals(field.getName())) {
try {
Expand All @@ -42,11 +45,34 @@ private static Object findBeanAt(List<String> fields, Object object) {
} catch (IllegalAccessException e) {}
}
}

throw new IllegalArgumentException();
}

private static String headOf(final Collection<String> paths) {
return paths.iterator().next();
}

private static List<Field> getAllFields(Class<?> type) {
List<Field> allFields = new LinkedList<Field>();
for (Class<?> clazz = type; clazz != null; clazz = clazz.getSuperclass()) {
List<Field> fields = new LinkedList<Field>();
for (Field field : clazz.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (fieldIsVisibleInType(clazz, modifiers, type)) {
fields.add(field);
}
}
allFields.addAll(fields);
}
return allFields;
}

private static boolean fieldIsVisibleInType(Class<?> clazz, int modifiers, Class<?> type) {
return isProtected(modifiers) || isPublic(modifiers) || isDefault(modifiers) || clazz.equals(type);
}

private static boolean isDefault(int modifiers) {
return modifiers == 0x0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.shazam.shazamcrest;

import org.junit.Test;

import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static org.hamcrest.Matchers.startsWith;

public class CustomMatcherOnInheritedFieldTest {

@Test
public void inheritedFieldsAreMatchedByCustomMatchers() {
assertThat(new ChildClass(), sameBeanAs(new ChildClass())
.with("packageProtectedField", startsWith("inherit"))
.with("protectedField", startsWith("inherit"))
.with("publicField", startsWith("inherit"))
);
}

@Test
public void notInheritedFieldsAreMatchedByCustomMatchers() {
assertThat(new ChildClass(), sameBeanAs(new ChildClass())
.with("childField", startsWith("child"))
);
}

@Test(expected = IllegalArgumentException.class)
public void inheritedPrivateFieldsCanNotBeMatched() {
assertThat(new ChildClass(), sameBeanAs(new ChildClass())
.with("privateField", startsWith("foo"))
);
}

@SuppressWarnings("unused")
private class GrandParentClass {
private String privateField = "not inherited";
String packageProtectedField = "inherited";
}

@SuppressWarnings("unused")
private class ParentClass extends GrandParentClass {
protected String protectedField = "inherited";
public String publicField = "inherited";
}

@SuppressWarnings("unused")
private class ChildClass extends ParentClass {
private String childField = "child field";
}
}

0 comments on commit 87f9172

Please sign in to comment.