5

Given a list of objects I'd like to test that they return in the correct order, but I would like to not assert the entire object.

For example I'd like to verify that they're in order by

id 1, 
id 2,
id 3,

or in another case

date mostRecent
date older
date oldest

or in yet another case

enum ValueA
enum ValueB
enum ValueC

basically I want to test that the sort I specified went through correctly but only a single property on the object actually affects this, so I'd like to specify my test with some variant of hasFirstItem( withPropertyEqualTo ... has secondItem( withPropertyEqualTo

I know I can write

 assertEquals( property, list.get(0).id )
 assertEquals( property, list.get(1).id )

but I'd rather do something that makes the failure a bit more obvious as to being a sort issue, and perhaps declaratively, testing the whole collection at once. Is this possible?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
xenoterracide
  • 16,274
  • 24
  • 118
  • 243
  • 1
    Can you use Java 8? If so, I might map the property function over the list and assert on the result. – Louis Wasserman Jun 02 '15 at 17:20
  • JUnit/Hamcrests [`assertThat(actual, contains(item1, item2, ...));`](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#contains%28E...%29) should exaclty do this. You can even write own Matchers that do the check as you want – Roman Vottner Jun 02 '15 at 17:35

5 Answers5

4

You should be able to use hamcrest's matcher hasProperty like this:

public class Foo {

    private String a;

    public Foo(String a) {
        this.a = a;
    }

    public Object getStr() {
        return a;
    }


    public static void main(String[] args) {
        List<Foo> l = Arrays.asList(new Foo("a"), new Foo("b"));
        Assert.assertThat(l, contains(hasProperty("str", equalTo("a")),
                                      hasProperty("str", equalTo("b"))));
    }

}

where "str" is the name of the property you want to check. Note that this only works for methods named getXxx as it is aimed to test JavaBeans.

K Erlandsson
  • 13,408
  • 6
  • 51
  • 67
  • isn't `contains` unordered?meaning that if `new Foo("b")` is the first object it'll still pass? – xenoterracide Jun 02 '15 at 18:28
  • 2
    No, [containsInAnyOrder](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html#containsInAnyOrder%28java.util.Collection%29) checks unorded wise. contains will check item1 against item1 and so on – Roman Vottner Jun 02 '15 at 18:30
  • naming... thanks, I assumed incorrectly that contains, was similar in function to a Collection.contains. – xenoterracide Jun 02 '15 at 18:41
  • @xenoterracide agreed, it would make more sense and be less confusing to have `containsInOrder` and `contains` (in any order) IMO – K Erlandsson Jun 02 '15 at 18:43
2

One way to go about this would be to simply sort your list according to the given property and then compare the sorted list to the original:

public class MyObjectIdComparator implements Comparator<MyObject> {

    @Override
    public int compare (MyObject a, MyObject b) {
        return a.getId().compareTo(b.getId());
    }
}

ArrayList<MyObject> orig = getListFromSomewhere();
ArrayList<MyObject> sorted = new ArrayList<>(orig);
Collections.sort (sorted, new MyObjectIdComparator());

assertEquals ("orig list is in the wrong order, sorted, orig);
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Shouldn't you be using `assertNotEquals` instead of `assertEquals` for the test to pass? – Chetan Kinger Jun 02 '15 at 17:39
  • @ChetanKinger The way I understand the OP, he has "production" code that generates a list in a way that's ordered by some property. If explicitly sorting the list by that property does **not** change it we can deduce it was already sorted, as expected - hence, the use of `assertEquals`. – Mureinik Jun 02 '15 at 18:03
  • `assertEquals` would make sense in that case. That being said, I am unable to find enough content in the OP that supports your explanation. – Chetan Kinger Jun 02 '15 at 18:37
1

Can you iterate over the collection and report the first case where the property of interest failed?

for (int i=0; i<list.size()-1; ++i) {
 if (list.get(i) > list.get(i+1)) {
    fail(String.format("%s > %s; in the wrong place in the sorted list for index %d",
        list.get(i), list.get(i+1), i));
 }
}
Jerry Andrews
  • 847
  • 5
  • 23
0

You can specify a message in your assert command,

assertEquals("Sort out of order at index " + i, expected.get(i), list.get(i));

or,

assertSame("Sort out of order at index " + i, expected.get(i), list.get(i));
Dhanuka
  • 2,826
  • 5
  • 27
  • 38
user3294068
  • 340
  • 2
  • 6
0

Assuming that property object implements Comparable interface:

Object previous = list.get(0);

for (Object element : list) {
    assertTrue(previous.getProperty().compareTo(element.getProperty()) <= 0);
    previous = element;
}
Simimmo
  • 658
  • 1
  • 6
  • 15