hamcrest / JavaHamcrest

Java (and original) version of Hamcrest
http://hamcrest.org/
BSD 3-Clause "New" or "Revised" License
2.11k stars 379 forks source link

HasProperty Matcher doesn't work with Java Records #392

Open rozagerardo opened 2 years ago

rozagerardo commented 2 years ago

Describe the bug I have the following simple assertion in my test:

hasProperty("name")

For the following record:

public record AnyDto(
    Long id,

    @NotBlank
    String name,

    String description) { }

And even though I can see the object does have the property (set with a value), the test fails.

I have tracked this down, and it seems the "issue" is generated in the PropertyUtil class, in the propertyDescriptorsFor method:

https://github.com/hamcrest/JavaHamcrest/blob/5d76642543b4d8c3e5f1b4cd4684d31be0724fde/hamcrest/src/main/java/org/hamcrest/beans/PropertyUtil.java#L49

This is what Introspector.getBeanInfo(fromObj.getClass(), stopClass) retrieves for a Record class:

Screen Shot 2022-10-26 at 15 17 30

If I change the AnyDto to a regular class, the test passes, because the Introspector method above does contain PropertyDescriptors for the class:

Screen Shot 2022-10-26 at 15 21 48

Note: the Record does contain name as a MethodDescriptor, maybe we can rely on these for the Records?

This is a related Stackoverflow Question: https://stackoverflow.com/questions/66982522/how-can-i-assert-hasproperty-with-a-java-record

CC007 commented 1 year ago

It would be nice if property descriptors would be supplemented with Class::getRecordComponents in the case that Class::isRecord is true

djkeh commented 3 months ago

Is this still on the go? I strongly hope to see this happening. More and more people start using records for handler methods in spring boot.

tumbarumba commented 3 months ago

@djkeh yes, I'm looking to do something to fix this in the next release.

tumbarumba commented 3 months ago

I had a closer look at this issue. I don't think I can put a fix in for it right now. I'd like to keep the v3.x versions all compatible with Java 1.8. From v4.x, I will look to introduce features for more modern JVMs and runtime libraries.

Unfortunately, I don't have a timeline for how long it will take. I think there is a prerequisite for implementing JEP 238 support, which should give the forward/backward compatibility guarantees I think Hamcrest should support.

djkeh commented 2 weeks ago

@tumbarumba I created a PR for this issue: #426 This pr keeps current java version 8 and introduces MethodUtil to deal with the whole regular methods in a class using MethodDescriptor. The idea is that if the class has a non-void method with the exact same name to the given property name, hasProperty() will regard it as a property. In this manner we will be able to validate record classes leaving Hamcrest's current java version. Please have a look.

tumbarumba commented 1 week ago

Thanks for this @djkeh! I'll have a closer look over the next few days and get back to you