Подтвердить что ты не робот

Java Hamcrest: коллекция содержит элемент типа

Я хотел бы утверждать, что List<Achievement> содержит член типа TestAchievement.

Здесь мое утверждение:

List<Achievement> achievements; // Populated elsewhere
assertThat(achievements,hasItem(isA(TestAchievement.class)));

Это не компилируется, сообщая об ошибке:

Метод assertThat (T, Matcher) в типе Assert не применимо для аргументов (List, Сличитель < Iterable < TestAchievement → )

Какой правильный синтаксис для этого типа утверждения с использованием Hamcrest?

4b9b3361

Ответ 1

Спасибо за помощь.

Посты здесь предположили, что это был дефект с Hamcrest, поэтому я направился на сайт hacmrest, чтобы зарегистрировать ошибку, в то время как я обнаружил, что объявление зависимости mvn/ivy, которое я использовал, было устаревшим, давая мне старой версии Hamcrest.

Эта ошибка существует с 1.1, которая является последней, если объявлена ​​с использованием

<dependency org="org.hamcrest" name="hamcrest-all" rev="1.1">

Тем не менее, правильная декларация о допустимости:

<dependency org="org.hamcrest" name="hamcrest-library" rev="1.3.RC2"/>

Обновление для этого позволило решить проблему. Синтаксис, используемый в моем тесте:

 assertThat(achievements, hasItem(isA(TestAchievement.class)));

Ответ 2

В Java 6 есть bug, который относится к этому.

Этот код будет генерировать различные ошибки, такие как "не удается найти символ..."

assertThat(achievements, hasItem(isA(TestAchievement.class)));

Работа для этого состоит в том, чтобы объявить совпадение как переменную, а затем ссылаться на эту переменную. Важно отметить, что тип переменной, в частности раздел дженериков, очень важен для этого.

Matcher<Iterable<? super TestAchievement>> matcher = hasItem(isA(TestAchievement.class));
assertThat(achievements, matcher);

Интересно, если вы используете instanceOf() вместо isA(), вы снова столкнетесь с проблемой. (хотя, если вы игнорируете предупреждения, это может просто работать для вас в любом случае.) Развернув предыдущее исправление, вы можете использовать:

Matcher<TestAchievement> itemMatcher = Matchers.instanceOf(TestAchievement.class);
Matcher<Iterable<? super TestAchievement>> matcher = hasItem(itemMatcher);
assertThat(achievements, matcher);

Ответ 3

assertThat(achievements, hasItem(
    IsInstanceOf.<Achievement>instanceOf(TestAchievement.class)));

Ответ 4

Я боролся с этим какое-то время, ни один из подходов здесь не имел ожидаемого результата. Из чистого отчаяния я попытался преобразовать в массив, чтобы узнать, не изменилось ли это:

List<Object> listOfThings = (List) someService.findThings(); // your business logic here
Object[] arrayOfThings  = listOfThings.toArray(new Object[listOfThings.size()]);

assertThat(arrayOfThings, hasItemInArray(instanceOf(SpecialThing.class)));

И это действительно имело значение. Теперь мой тест работает безупречно. Одна строка из массива "копирование в массив" представляется разумным компромиссом, чтобы сэкономить много хлопот.

Ответ 5

Я некоторое время размышлял об этом с этим, и кажется, что единственный способ, которым я знаю, - преобразовать List<Achievement> в List<Object>. Задача CoreMatchers.instanceOf() возвращает Matcher<Object>.

С этой модификацией я могу заставить это работать: -

List<Object> achievements = new ArrayList<Object>();
achievements.add(new Achievement());
achievements.add(new TestAchievement());
assertThat(achievements, hasItem(instanceOf(TestAchievement.class)));

Ответ 6

От http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java подпись

assertThat(T actual, Matcher<? super T> matcher)

поэтому проблема заключается в том, что ваш помощник - это Matcher<TestAchievement>, а не помощник, который работает для любого экземпляра суперкласса или интерфейса достижения.

Похоже, что у instanceOf -сервер только есть привязка типа багги. Вы можете обойти эту ошибку, сделав что-то вроде

@SuppressWarnings("unchecked")
Matcher/*no_param*/ isATestAchievement = instanceOf(TestAchievement.class);
assertThat(..., isATestAchievement);

Ответ 7

Actuall это не работает для немного более сложного Matcher, даже используя последнюю версию.

assertThat(result.getAnswers(),
            Matchers.hasItem(Matchers.hasProperty("content")));

Это не сработает, вы получите:

Метод assertThat (T, Matcher) в типе Assert не применим для аргументов (Set, Matcher > )

Вы можете решить это, преобразовывая его в массив:

assertThat(result.getAnswers().toArray(), hasItemInArray(Matchers.hasProperty("content", equalTo("<h4>new comment</h4>"))));