testing the order of a collection
Asked Answered
H

5

6

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?

Honaker answered 2/6, 2015 at 17:18 Comment(2)
Can you use Java 8? If so, I might map the property function over the list and assert on the result.Cherida
JUnit/Hamcrests assertThat(actual, contains(item1, item2, ...)); should exaclty do this. You can even write own Matchers that do the check as you wantTipcat
D
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.

Decoct answered 2/6, 2015 at 17:41 Comment(4)
isn't contains unordered?meaning that if new Foo("b") is the first object it'll still pass?Honaker
No, containsInAnyOrder checks unorded wise. contains will check item1 against item1 and so onTipcat
naming... thanks, I assumed incorrectly that contains, was similar in function to a Collection.contains.Honaker
@Honaker agreed, it would make more sense and be less confusing to have containsInOrder and contains (in any order) IMODecoct
M
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);
Mcewen answered 2/6, 2015 at 17:25 Comment(3)
Shouldn't you be using assertNotEquals instead of assertEquals for the test to pass?Lem
@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.Mcewen
assertEquals would make sense in that case. That being said, I am unable to find enough content in the OP that supports your explanation.Lem
W
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));
 }
}
Wail answered 2/6, 2015 at 17:28 Comment(1)
Perhaps you meant list.get(i) > list.get(i+1)Ovarian
H
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));
Howze answered 2/6, 2015 at 17:25 Comment(0)
H
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;
}
Higley answered 2/6, 2015 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.