Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable custom matching on inherited fields #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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";
}
}