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
RecursiveComparisonAssert: improvement for comparing field with different types in actual and expected objects. #3165
Comments
@pcuriel could you show us on an example what the use of these new methods would look like compared to the existing API ? |
For sure. Continuing with my example above. If we have these: class Foo {
LocalTime time;
}
class FooDto {
String time;
} With the new methods, the idea is that instead of this: assertThat(foo)
.usingRecursiveComparison()
.withEqualsForType((BiPredicate<LocalTime, Object>) (time, timeStr) -> time.equals(LocalTime.parse((String) timeStr)), LocalTime.class)
.isEqualTo(fooDto); We would be able to do this: assertThat(foo)
.usingRecursiveComparison()
.withEqualsForTypes((time, timeStr) -> time.equals(LocalTime.parse(timeStr)), LocalTime.class, String.class)
.isEqualTo(fooDto);
class Bar {
LocalTime time;
LocalDate date;
}
class BarDto {
String time;
String date;
} And we want to assert that BarDto is equal to Bar, using "withEqualsForType" does not work: DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
assertThat(barDto)
.usingRecursiveComparison()
// This is overridden...
.withEqualsForType((BiPredicate<String, Object>) (dateStr, date) -> dateStr.equals(dateFormatter.format((LocalDate) date)), String.class)
// when registering this
.withEqualsForType((BiPredicate<String, Object>) (timeStr, time) -> timeStr.equals(timeFormatter.format((LocalTime) time)), String.class)
.isEqualTo(bar); While "withEqualsForTypes" should be OK, because one is registered with String & LocalDate, whereas the other is registered with String & LocalTime: ...
.withEqualsForTypes((dateStr, date) -> dateStr.equals(dateFormatter.format(date)), String.class, LocalDate.class)
.withEqualsForTypes((timeStr, time) -> timeStr.equals(timeFormatter.format(time)), String.class, LocalTime.class)
... With objects so simple as the ones used here it is true that we can just resort to using "withEqualsForFields" as explained in my initial post. |
Yeah, fair enough, would have time contributing this one ? |
Currently I don't have much time, but I'll try to work on it if it's still pending in a few weeks. |
I can take it if you would |
@amodolo thanks ! |
When using RecursiveComparisonAssert to compare objects of different Classes (e.g., Foo and FooDto), we may have the same fields but with different types (e.g., LocalTime and String).
In these cases, comparison will fail by default.
We can use withEqualsForType, withComparatorForType, withEqualsForFields and withComparatorForFields methods to customize comparison.
For instance, given:
We can do any of these:
The "ForFields" methods just require casting the values (or the BiPredicate in the withEquals case), so they look OK.
However, the "ForType" methods look to hacky, requiring an ugly double casting. I addition, while registering a withComparatorForType using LocalTime may work well (to assert Foo against FooDto), registering it using String (to assert FooDto against Foo) will most likely break equality tests for other fields in the class.
To solve these issues, would it be feasible to add two-type versions of these methods?
The text was updated successfully, but these errors were encountered: