buræquete
buræquete

Reputation: 14678

Hamcrest matcher fails to match Boolean type property

For class A;

public class A {
    Integer value;
    Integer rate;
    Boolean checked;
}

I am constructing a custom Matcher like this;

Matchers.hasItems(allOf( hasProperty("value", equalTo(value)), hasProperty("rate", equalTo(rate))))

to check if a list of A contains the one with "value" == value && "rate" == rate

The problem I have is that, when I incorporate the Boolean type property checked as a constraint to this Matcher, it always fail with error msg property "checked" is not readable.

Matchers.hasItems(allOf( hasProperty("value", equalTo(value)), hasProperty("rate", equalTo(rate)), hasProperty("checked", equalTo(checked))))

Is it somehow related to the getter methods of boolean type fields have is prefix rather than get, and may be Hamcrest fail to use is prefix for getter if it is not boolean but Boolean type field.

Also, I should add that I cannot modify the structure of class A, therefore I am stuck with Boolean type fields.

Upvotes: 1

Views: 2534

Answers (1)

buræquete
buræquete

Reputation: 14678

Nobody responded to this question, but I have implemented my own HasPropertyWithValue class with this small modification in propertyOn method where is generates a PropertyDescriptor of the given bean and property name.

private Condition<PropertyDescriptor> propertyOn(T bean, Description mismatch) {
    PropertyDescriptor property = PropertyUtil.getPropertyDescriptor(propertyName, bean);
    if (property != null) {
        if (property.getReadMethod() == null && property.getPropertyType().equals(Boolean.class)) {
            String booleanGetter = "is" propertyName.substring(0, 1).toUpperCase() propertyName.substring(1);
            for(Method method : bean.getClass().getDeclaredMethods()) {
                if (method.getName().equals(booleanGetter)) {
                    try {
                        property.setReadMethod(method);
                    } catch (IntrospectionException e) {
                        throw new IllegalStateException("Cannot set read method" e);
                    }
                }
            }
        }
    } else {
        mismatch.appendText("No property \"" + propertyName + "\"");
        return notMatched();
    }

    return matched(property, mismatch);
}

Where after the creation of PropertyDescriptor, where is has null readMethod. I used Java Reflection to get the correct Boolean getter method that starts with is prefix, and add it to the property as readMethod. This has solved the issue, but in such an ugly way.

I also created a pull request for Hamcrest project in GitHub; https://github.com/hamcrest/JavaHamcrest/pull/136

Upvotes: 2

Related Questions