Assertj: Using the index when asserting list elements via predicate

71 Views Asked by At

I want to assert items based on their index in the list under test.

While doing some research I came across this solution, which works:

    // This works:
    assertThat(tasks).extracting(Task::getId, Task::getExamId).containsExactly(
            tuple(1, EXAM_ID),
            tuple(2, EXAM_ID),
            tuple(3, EXAM_ID),
            tuple(4, EXAM_ID),
            tuple(5, EXAM_ID)
    );

However I am looking for something more dynamic, FOR EXAMPLE (doesn't compile)

    // I would rather use something like
    BiFunction<Integer, Task, Boolean> indexedPredicate = (n, task) -> Objects.equals(task.getId(), n);
    assertThat(tasks).allSatisfy(indexedPredicate);

I had a good look at all available methods but couldn't find anything. Any ideas?strong text

3

There are 3 best solutions below

1
samabcde On BEST ANSWER

As we wanted to assert the relation between index and the element, how about converting the list to index-element map first?

Then we could call allSatisfy to assert the relationship.

import static java.util.stream.Collectors.toMap;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.stream.IntStream;

public class AssertIndexedElementOfListTest {
    record Task(int id, String examId) {
    }

    @Test
    public void assertTest() {
        List<Task> tasks = List.of(
                new Task(0, "EXAM_0"),
                new Task(1, "EXAM_1"),
                new Task(2, "EXAM_2"),
                new Task(3, "EXAM_3")
        );
        var indexTaskMap = IntStream.range(0, tasks.size())
                .boxed()
                .collect(toMap(i -> i, tasks::get));
        assertThat(indexTaskMap).allSatisfy(
           (index, task) -> assertThat(task.id()).isEqualTo(index)
        );
    }
}

Reference: How to convert List to Map with indexes using stream - Java 8?

0
Joel Costigliola On

I confirm that does not exist in AssertJ, I think you already have the best workaround wiht containsExactly, you could also use isEqualTo and build the expected collection, a bit simpler but requires to setup the expected result.

1
knittl On

Not sure if I completely understood, but it sounds like you want to assert that the items in your list contains an ID that matches the index/offset in the list?

assertThat(tasks).extracting(Task::getId)
    .containsExactlyElementsOf(IntStream.range(0, tasks.size()).boxed().toList());

IntStream.range(0, tasks.size()).boxed().toList() produces a list of the indices/offsets in your list.