hamcrest-optional
hamcrest-optional copied to clipboard
improve method signatures for nested generics
Thanks for your library, which I have been using for many years.
I just run into a problem with nested generics inside Optional<>
. Let's say I have a method that returns an Optional<Map<Integer, BigDecimal>>
:
Optional<Map<Integer, BigDecimal>> foo() {
//TODO
}
I try to test it like this:
assertThat(foo(),
isPresentAndIs(Map.of(1, BigDecimal.valueOf(123), 2, BigDecimal.valueOf(456))));
This doesn't compile on Eclipse 2022-06 using Java 17. It gives me:
The method assertThat(T, Matcher<? super T>) in the type MatcherAssert is not applicable for the arguments (Optional<Map<Integer,BigDecimal>>, Matcher<Optional<Map<Integer,BigDecimal>>>)
Because the second argument in assertThat()
uses Matcher<? super T>
, apparently it doesn't realize that one Optional<Map<Integer,BigDecimal>>
is equivalent to another. (If I haven't interpreted this correctly, let me know.)
The signature to isPresentAndIs()
is:
public static <T> Matcher<Optional<T>> isPresentAndIs(T operand)
If I change it to the following, the test will compile:
public static <T> Matcher<? super Optional<T>> isPresentAndIs(T operand)
I think you need a bunch of ? super
sprinkled throughout your API.
Interestingly I can create a workaround simply by adding this method inside the test itself!
public static <T> Matcher<? super Optional<T>> isPresentAndIs(T operand) {
return OptionalMatchers.isPresentAndIs(operand);
}
Apparently there is just some type inference that Java just can't handle without help.