shazam/shazamcrest

sameBeanAs(...).with("inheritedField", matcher) fails with "inheritedField does not exist" if set to check inherited field

kozlovda opened this issue · 0 comments

Hi,

The issue above happens when field is inherited from one of super-classes of the tested bean.

This happens due to shallow lookup of the field at BeanFinder.java:33:

    private static Object findBeanAt(List<String> fields, Object object) {
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);

As per getDeclaredFields() javadoc it doesn't return inherited fields:

This includes public, protected, default (package) access, and private fields, but excludes inherited fields.

Basically, it seems reasonable to update field lookup to search through inherited fields as well (with all field shadowing logic in place).

Thanks in advance for looking into this!

Update

Shadowing is not supported by GSON, so this goes off.

Test case:

import org.junit.Test;

import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

public class InheritedFieldTest {
    @Test
    public void testBeanMatcherWithDefaultCheck() throws Exception {
        final MyBean bean = new MyBean();

        bean.setOwn("own");
        bean.setInheritedField("inherited");

        final MyBean expected = new MyBean();
        expected.setOwn("own");
        expected.setInheritedField("inherited");

        assertThat(bean, is(sameBeanAs(expected)));
    }

    @Test
    public void testBeanMatcherWithCustomCheck() throws Exception {
        final MyBean bean = new MyBean();

        bean.setOwn("own");
        bean.setInheritedField("inherited");

        final MyBean expected = new MyBean();

        assertThat(bean, is(sameBeanAs(expected)
                .with("own", is("own"))
                .with("inheritedField", is("inherited"))
        ));
    }

    @SuppressWarnings("UnusedDeclaration")
    public static class MyBean extends BaseBean {
        private String own;

        public String getOwn() {
            return own;
        }

        public void setOwn(String own) {
            this.own = own;
        }
    }

    @SuppressWarnings("UnusedDeclaration")
    public static class BaseBean {
        private String inheritedField;

        public String getInheritedField() {
            return inheritedField;
        }

        public void setInheritedField(String inheritedField) {
            this.inheritedField = inheritedField;
        }
    }
}