alonso_50
alonso_50

Reputation: 1542

Assert two List have same subtypes in a certain order

I would like to check if two lists (let's say, ArrayLists) have exactly the same instance classes, based in an expected List. To do so, I have built the next method, but I was wondering whether there is another fancy way using certain library, like assertJ.

    private void assertConcreteTypes(List actual, List expected) {
        for (int i = 0; i < actual.size(); i++){
            assertThat(actual.get(i)).isExactlyInstanceOf(expected.get(i).getClass());
        }
    }

Any suggestion would be more than welcome. Thanks!

Upvotes: 0

Views: 458

Answers (2)

Govinda Sakhare
Govinda Sakhare

Reputation: 5749

You can create a custom Assertj asserter and leverage it for asserting types.

class TypeAssert extends AbstractAssert<TypeAssert, List<?>> {

    public TypeAssert(List<?> actual) {
        super(actual, TypeAssert.class);
    }

    public TypeAssert hasElementsOfExactlyTheSameTypeAs(List<?> expected) {
        isNotNull();
        for (int i = 0; i < actual.size(); i++) {
            if (!actual.get(i).getClass().equals(expected.get(i).getClass())) {
                failWithMessage("Expected [%s]th element to be of type: %s but was of type: %s",
                    i, expected.get(i).getClass(), actual.get(i).getClass());
            }
        }

        return this;
    }
}

You'll need a static method that will expose the object of our Custom Exporter.

class Assertions {

    // static factory method which exposes custom asserted
    static TypeAssert assertThat(List<?> actual) {
        return new TypeAssert(actual);
    }
}

And then you can use the above method for asserting based on type.

List<Object> actual = List.of(new Employee());
List<Object> expected = List.of(new StringBuilder());

Assertions.assertThat(actual).hasElementsOfExactlyTheSameTypeAs(expected);

If you are asserting based on a type only at a very few places then I think the approach you have mentioned is much cleaner and readable. But if you need such assertion at several places then may be creating a custom assertion is a good choice.

Upvotes: 1

Delta George
Delta George

Reputation: 4236

You need to take into account lists of different sizes as well as null elements in the lists.

This seems quite readable and caters to these edge cases:

private void assertConcreteTypes(List actual, List expected) {
    assertEquals(classes(expected), classes(actual));
}

private List<Class<?>> classes(List<Object> list) {
    return list.stream().map(v -> v == null ? null : v.getClass()).collect(Collectors.toList());
}

Upvotes: 0

Related Questions