Ok I think its going to be a short question. I have an ArrayList that I sorted by date, of course I see it works but I would also like to write a test for it.
I want to check if next value (date) in my list is lower then previous one. I am able to do that with using some for
s and adding temp list, but I'm wondering if there's a easier solution. I read in hamrest documentation that there's somethink like contains
(hamrest contains) that iterate through an object (list,map etc) but still I have no idea what to do next.
Instead just iterate over the list and check that the current element is greater or equal than the previous. If your list should be sorted in descending order check that the current element is less or equal than previous. Obviously the comparison of elements may be done using custom Comparator . Save this answer.
Iterative Approach The iterative approach is a simple and intuitive way to check for a sorted list. In this approach, we'll iterate the list and compare the adjacent elements. If any of the two adjacent elements are not sorted, we can say that the list is not sorted.
Java List sort() Method. The sort() method of List Interface sorts the given list according to the order specified in the comparator. The list must be modifiable else it will throw an exception.
assertThat method is deprecated. Its sole purpose is to forward the call to the MatcherAssert. assertThat method defined in Hamcrest 1.3. Therefore, it is recommended to directly use the equivalent assertion defined in the third party Hamcrest library.
[First Option]: you can write your own Matcher. Something like (disclaimer: this is just a sample code, it is not tested and may be not perfect):
@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;
}
};
}
This example is with Integer
s but you can do it with Date
s easily.
[Second option], based on the reference to contains
in the OP's question: you can create a second list, ordering the original one, than using assertThat(origin, contains(ordered))
. This way the eventual error is more precisely described since, if an element is not in the expected order, it will be pointed out. For example, this code
@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()));
}
will generate the description
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)
...
There's an open request for such a matcher, but unfortunately it isn't implemented yet.
I'd go for something much simpler - copy the list, sort it, and compare to the original:
@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 has a good point in the comments - while (relatively) elegant, this solution is not designed with any performance consideration. If the list isn't too large it should be OK, but if the list is large, sorting it may be costly. If the list is large, it may be a good idea to iterate over it directly, and fail the test if you encounter an element that is smaller than the previous one. E.g.:
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;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With