assertThat - hamcrest - проверить, если список отсортирован
хорошо, я думаю, что это будет короткий вопрос. У меня есть ArrayList, который я отсортировал по дате, конечно, я вижу, что он работает, но я также хотел бы написать тест для него.
Я хочу проверить, является ли следующее значение (дата) в моем списке ниже предыдущего. Я могу сделать это с помощью некоторых for
s и добавление списка temp, но мне интересно, есть ли более простое решение. Я читал в документации hamrest, что есть что-то вроде contains
(содержит hamrest), которые проходят через объект (список, карта и т. д.), Но я все еще не знаю, что делать дальше.
6 ответов
[Первый Вариант]: вы можете написать свой собственный Matcher. Что-то вроде (отказ от ответственности: это всего лишь пример кода, он не тестируется и может быть не идеальным):
@Test
public void theArrayIsInDescendingOrder() throws Exception
{
List<Integer> orderedList = new ArrayList<Integer>();
orderedList.add(10);
orderedList.add(5);
orderedList.add(1);
assertThat(orderedList, isInDescendingOrdering());
}
private Matcher<? super List<Integer>> isInDescendingOrdering()
{
return new TypeSafeMatcher<List<Integer>>()
{
@Override
public void describeTo (Description description)
{
description.appendText("describe the error has you like more");
}
@Override
protected boolean matchesSafely (List<Integer> item)
{
for(int i = 0 ; i < item.size() -1; i++) {
if(item.get(i) <= item.get(i+1)) return false;
}
return true;
}
};
}
этот пример с Integer
S, но вы можете сделать это с Date
s легко.
[второй вариант], основываясь на ссылке на contains
в вопросе OP: вы можете создать второй список, заказав оригинальный, чем с помощью assertThat(origin, contains(ordered))
. Таким образом, возможная ошибка больше точно описано, так как, если элемент не находится в ожидаемом порядке, он будет указан. Например, этот код
@Test
public void testName() throws Exception
{
List<Integer> actual = new ArrayList<Integer>();
actual.add(1);
actual.add(5);
actual.add(3);
List<Integer> expected = new ArrayList<Integer>(actual);
Collections.sort(expected);
assertThat(actual, contains(expected.toArray()));
}
будет генерировать описание
java.lang.AssertionError:
Expected: iterable containing [<1>, <3>, <5>]
but: item 1: was <5>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:865)
at org.junit.Assert.assertThat(Assert.java:832)
...
здесь открыть запрос на такой сопоставитель, но, к сожалению, он еще не реализован.
Я бы пошел на что - то гораздо проще-скопируйте список, отсортируйте его и сравните с оригиналом:
@Test
public void testListOrder() {
ArrayList<SomeObject> original = ...;
ArrayList<SomeObject> sorted = new ArrayList<SomeObject>(original);
Collections.sort(sorted);
Assert.assertEquals ("List is not sorted", sorted, original);
}
EDIT:
@dsncode имеет хороший момент в комментариях-хотя (относительно) элегантный, это решение не разработано с учетом производительности. Если список не слишком велик, он должен быть в порядке, но если список Большой, его сортировка это может дорого стоить. Если список Большой, может быть хорошей идеей перебрать его напрямую и не выполнить тест, если вы столкнулись с элементом, который меньше предыдущего. Например.:
assertTrue(() -> {
Iterator<SomeClass> iter = list.iterator();
SomeClass prev = null;
if (iter.hasNext()) {
prev = iter.next();
}
SomeClass curr = null;
while (iter.hasNext()) {
curr = iter.next();
if (curr.compareTo(prev) < 0) {
return false;
}
prev = curr;
}
return true;
});
также можно проверить его с помощью GUAVA:
import com.google.common.collect.Ordering;
...
assertTrue(Ordering.natural().isOrdered(list));
подробнее здесь: как определить, отсортирован ли список на Java?
для небольших коллекций я предлагаю предоставить ожидаемую коллекцию, жестко закодированную в коде.
Это модульный тест и не должен содержать никакой логики.
После этого можно сравнить две коллекции. (используйте hamcrest
чтобы проверить эквивалент)
У меня была аналогичная проблема, я просто проверяю, больше ли следующее значение даты в миллисекундах/меньше, чем предыдущее в этом списке.
/**
* Test sort by date
*/
@Test
public void findAllMessagesSortByDate() {
Collection<Message> messages = messageService.getAllMessagesSortedByDate();
long previousTime = messages.iterator().next().getDate().getTimeInMillis();
for (Message message : messages) {
assertTrue(message.getDate.getTimeInMillis() <= previousTime);
previousTime = message.getMessageFolderTs().getTimeInMillis();
}
}
вы можете проверить мой ответ в другой теме, но подход остается прежним - вы должны проверить, если элементы в порядке.
Как проверить, содержит ли коллекция элементы в заданном порядке с помощью Hamcrest
этот подход предполагает использование библиотеки "Hamcrest".
надеюсь, что это помогает.