There are basically two options as I see it: You can use a library that will make writing of (some) tests more convenient, and you can rely on plain JUnit
and do everything else “by hand”.
For the library option, this is not my expertise, but I do know that there are a number to choose from. What pezetem writes in another answer about AssertJ sounds promising, particularly isSortedAccordingTo()
. It does require you to write a Comparator
for each of the sortings you want to check, though. I’d take a good look at the different libraries also with an eye to other tests than this one before making an informed choice.
If you prefer not to depend on a library for the purpose right now, I suggest you write yourself an auxiliary method like this:
private static <T extends Comparable<? super T>> boolean isSortedBy(Function<Book, T> getMethod, List<Book> list) {
if (list.isEmpty()) {
return true;
}
Iterator<Book> bit = list.iterator();
T attr = getMethod.apply(bit.next());
while (bit.hasNext()) {
T nextAttr = getMethod.apply(bit.next());
if (nextAttr.compareTo(attr) < 0) {
return false;
}
attr = nextAttr;
}
return true;
}
You will recognize the logic from this answer, but I have twisted the method signature to match your need here. Now your test is as simple as:
assertTrue(isSortedBy(Book::getName, listOfBooks));
Two notes though:
- I am assuming that your
Book
class has getters, and there are reasons why you may want to add them, not only for the unit test. If not, you may use isSortedBy(b -> b.name, listOfBooks)
.
- When you said collection, I assume you meant list. Other collection types (like sets) may not have an order, so it may not be meaningful to check whether they are sorted.
If you want your method more general, you may add another type parameter to allow lists of other things than books:
private static <E, T extends Comparable<? super T>> boolean isSortedBy(Function<E, T> getMethod, List<E> list)
For my part I would wait until I see a need though.
When writing unit tests I find it worth thinking about how test failures are reported to the tester, what information s/he will need if a test fails. Only knowing the the list wasn’t sorted accoring to the attribute it should be sorted by may not be that useful. Unless you list is long, I think that you may just dump the entire list as message:
assertTrue(listOfBooks.toString(), isSortedBy(Book::getName, listOfBooks));
(You will want to make sure your Book
class has a toString
method for this to be useful.) There are of course ways to do more refined failure reporting if you have the auxiliary method return a specific message rather than just true
or false
.