2

In AssertJ you can do the following to assert the contents of a list:

assertThat(list).extracting("name").containsExactlyInAnyOrder("Alice", "Bob");

I often find myself wanting to do more complex assertions on the elements themselves, e.g., asserting that Alice is a tall brunette and Bob is tiny and bald. What is the best way to do this using AssertJ?

My own solution is to do:

assertThat(list).extracting("name").containsExactlyInAnyOrder("Alice", "Bob");
list.stream()
    .filter(person -> "Alice".equals(person.getName()))
    .forEach(alice -> {
        assertThat(alice).extracting("size").isEqualTo("tall")
        assertThat(alice).extracting("hair").isEqualTo("brunette")
    });
list.stream()
    .filter(person -> "Bob".equals(person.getName()))
    .forEach(bob -> {
        assertThat(bob).extracting("size").isEqualTo("tiny")
        assertThat(bob).extracting("hair").isNull()
    });

or equivalently (java 7) :

assertThat(list).extracting("name").containsExactlyInAnyOrder("Alice", "Bob");
for(Person person : list){
    switch (testCase.getName()){
        case "Alice":
            assertThat(person).extracting("size").isEqualTo("tall")
            assertThat(person).extracting("hair").isEqualTo("brunette")
            break;
        case "Bob":
            assertThat(person).extracting("size").isEqualTo("tiny")
            assertThat(person).extracting("hair").isNull()
            break;
    }
}

but I am wondering if there is a better solution.

I like the fact that this solution makes a distinction between the expected elements being in the list and the elements themselves being correct.

neXus
  • 2,005
  • 3
  • 29
  • 53
  • This is a highly simplified example. I encounter the need for this complex assertions mostly when a class contains a collection and I want to do assertions on this inner collection as well. – neXus Oct 17 '17 at 14:31

3 Answers3

6

For filtering, you can directly use any flavor of filteredOn, then either allMatch or allSatisfy (when I say directly I mean no need to stream your collection in order to filter it).

I suggest to explore AssertJ API, you have other assertions like anySatisfy or using conditions with method like are, areAtLeast, ... the vast majority of the API has javadoc with examples to show how to use it.

Additionally one can have a look at the examples in the assertj-examples project.

Hope it helps

Joel Costigliola
  • 6,308
  • 27
  • 35
2
 @Test
 public void test(){
    assertThat(list).filteredOn(person -> person.getName().equals("Alice")).extracting("size").first().isEqualTo("tall");
    assertThat(list).filteredOn(person -> person.getName().equals("Alice")).extracting("hair").first().isEqualTo("brunette");
    assertThat(list).filteredOn(person -> person.getName().equals("Bob")).extracting("size").first().isEqualTo("tiny");
    assertThat(list).filteredOn(person -> person.getName().equals("Bob")).extracting("hair").first().isNull();
}
Enrico Giurin
  • 2,183
  • 32
  • 30
1

Often I find it's easier to just express the whole expected collection:

assertThat(list).containsOnlyElementsOf(Arrays.asList(
    new Person("Alice", "tall", "brunette"),
    new Person("Bob", "tiny", null)
)
MikeFHay
  • 8,562
  • 4
  • 31
  • 52
  • This only works if the element assertions are simple. In your answer the `Person`'s `equals` method needs to be implemented correctly and take into account all the values you want, and nothing more. I find this too restrictive. Sometimes I don't care about other fields. E.g., you could add to a person the shoe size, which would be taken into account in the equals method while in the test I don't care. – neXus Oct 17 '17 at 14:11