Java Hamcrest: коллекция содержит элемент типа - PullRequest
20 голосов
/ 13 февраля 2011

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

Вот мое утверждение:

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

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

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

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

Ответы [ 7 ]

21 голосов
/ 13 февраля 2011

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

В сообщениях здесь говорилось, что это был дефект в Hamcrest, поэтому я отправился на сайт hacmrest, чтобы зарегистрировать ошибку, когда обнаружил, что объявление зависимостей mvn / ivy Iбыл устаревшим, дав мне старую версию 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)));
9 голосов
/ 24 декабря 2013

В Java 6 есть ошибка , связанная с этим.

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

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

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

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 голосов
/ 14 декабря 2012

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

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

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

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

3 голосов
/ 13 февраля 2011
assertThat(achievements, hasItem(
    IsInstanceOf.<Achievement>instanceOf(TestAchievement.class)));
2 голосов
/ 15 апреля 2013

На самом деле это не работает для немного более сложного 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>"))));
2 голосов
/ 13 февраля 2011

С 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 matcher просто есть связанный тип ошибки. Вы можете обойти эту ошибку, выполнив что-то вроде

@SuppressWarnings("unchecked")
Matcher/*no_param*/ isATestAchievement = instanceOf(TestAchievement.class);
assertThat(..., isATestAchievement);
2 голосов
/ 13 февраля 2011

Я некоторое время возился с этим, и, похоже, единственный известный мне способ - конвертировать 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)));
...