I was working with a test helper method a colleague wrote that took in an arbitrary status code Matcher to test whether a status code matched a particular value, which was implemented under the hood using StatusResultMathers.is(Matcher<Integer> matcher). I had one use case where I didn't actually care to assert anything, so I wanted to pass in Hamcrest's Matchers.anything() to the method. However, Matchers.anything() returns a Matcher<Object>, not a Matcher<Integer>, so it cannot be used with StatusResultMathers.is.

I ended up rewriting my test to not require the use of this matcher, but regardless of this fact, pretty much any method that takes in a specific type of Matcher to match against an object (e.g. Matcher<Integer>) should be allowed to take in a Matcher that matches a superclass as well, since that's still applicable to the object being matched.

Therefore, I propose that this method (and any other such test method in Spring Test) have its input type relaxed to allow the given type or any supertype. For this specific case, StatusResultMathers.is(Matcher<Integer> matcher) should be changed to StatusResultMathers.is(Matcher<? super Integer> matcher).

Example

This fails to compile:

MockMvcResultMatchers.status().is(Matchers.anything());

Methods with this issue

A quick search of the Spring Test project reveals the following methods that could have their generics widened:

Additionally, there are five methods containing Matcher<T> matcher, Class<T> targetType which I think could be widened to being Matcher<? super T> matcher, Class<T> targetType to allow a more general Matcher than the target type:

  • JsonPathAssertions.value(Matcher<T> matcher, Class<T> targetType)
  • JsonPathExpectationsHelper.assertValue(String content, Matcher<T> matcher, Class<T> targetType)
  • JsonPathRequestMatchers.value(Matcher<T> matcher, Class<T> targetType)
  • JsonPathResultMatchers.value(Matcher<T> matcher, Class<T> targetType)
  • MockMvcResultMatchers.jsonPath(String expression, Matcher<T> matcher, Class<T> targetType)

Comment From: rstoyanchev

Yes this seems to be inconsistent across ResultMatchers.