Как я могу получить contains(список itemMatchers) для компиляции в Java 7?


Я изучаю Hamcrest 1.3 и хочу придумать пример для каждого статического метода Hamcrest вMatchers . Javadoc услужливо уже имеет примеры для некоторых методов. Я протестировал следующийсодержит фрагмент кода с Java 8, и он прошел:

assertThat(Arrays.asList("foo", "bar"), 
           contains(Arrays.asList(equalTo("foo"), equalTo("bar"))));
Тем не менее, моя команда в настоящее время использует Java 7, поэтому я хотел убедиться, что все примеры работают в этой версии. Приведенный выше фрагмент кода приводит к следующей ошибке в Java 7:

Нет подходящего метода найдено для assertThat(java.утиль.Список, орг.hamcrest.Совпадение>>>) метод орг.тесты JUnit.Утверждать.assertThat(T, орг.hamcrest.Совпадений) не применяется (фактический аргумент орг.hamcrest.Matcher > > > не может быть преобразован в org.hamcrest.Matcher> по методу преобразования вызова) метод орг.тесты JUnit.Утверждать.assertThat (Ява.яз..Строка, Т, орг.hamcrest.Совпадений) не применяется (невозможно создать экземпляр из аргументов, поскольку фактические и формальные списки аргументов отличаются по длине)

Я знаю. что Java 8 добавила новые неявные функции типирования для статических методов, и я думаю, что это, вероятно, связано. Я попытался рефакторировать параметры и привести их к ожидаемым аргументам, но это приводит к той же ошибке:

List<String> actual = Arrays.asList("foo", "bar");
List<Matcher<String>> expected = Arrays.asList(equalTo("foo"), 
                                               equalTo("bar"));
assertThat(actual, contains(expected));

Как правильно вызывать static <E> Matcher<java.lang.Iterable<? extends E>> contains(java.util.List<Matcher<? super E>> itemMatchers) в Java 7?

2 5

2 ответа:

В Hamcrest Javadoc сигнатура метода для contains(), на который вы нацелены, является:

 public static <E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers);

Важным битом, который следует отметить в приведенной выше сигнатуре, является List<Matcher<? super E>>. Java 7 не может вывести List<Matcher<? super E>> из List<Matcher<String>>. contains() дополнительно перегружен, поэтому сигнатура метода, который нацелен на Java 7, является:

public static <E> Matcher<Iterable<? extends E>> contains(E... items);

И именно по этой причине вы получаете сообщение об ошибке компиляции cryptic!

К счастью, исправление довольно простое:

List<String> actual = Arrays.asList("foo", "bar");
List<Matcher<? super String>> expected = Arrays.<Matcher<? super String>>asList(equalTo("foo"), 
                                                                                equalTo("bar"));
assertThat(actual, contains(expected));

У меня нет установленных библиотек, чтобы легко проверить это, но я думаю, что это проблема подтипов.

  • expected имеет тип List<Matcher<String>>
  • contains(expected) имеет тип Matcher<Iterable<String>>
  • actual имеет тип List<String>
  • assertThat требуется первый аргумент типа T и второй типа Matcher<T>
  • Ваш T является List<String>, что означает, что он ожидает второй аргумент типа Matcher<List<String>>, а не Matcher<Iterable<String>>.

Я предполагаю, что это должно исправить это:

Iterable<String> actual = Arrays.asList("foo", "bar");
List<Matcher<String>> expected = Arrays.asList(equalTo("foo"), 
                                               equalTo("bar"));
assertThat(actual, contains(expected));

Опять же, я этого не сделал. протестировал это исправление-но похоже, что оно прояснит проблемы типа.