How to perform AssertJ recursive comparison with strict type checking only on collection elements?

315 views Asked by At

I would like to compare two collections using AssertJ with strict type checking. However, I only care about the strict types of collection elements not the collection itself.

For instace in the case below I would like assertion assertThat(listOfA).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(arrayListOfA) to be true while now it's false because listOfA is of type SingletonList and arrayListOfA is of type ArrayList

@Test
fun `test`() {
    val listOfA = listOf(TestClassA("Name"))
    val arrayListOfA = arrayListOf(TestClassA("Name"))
    val arrayListOfB = arrayListOf(TestClassB("Name"))
    assertThat(listOfA).usingRecursiveComparison().isEqualTo(arrayListOfA)
    assertThat(listOfA).usingRecursiveComparison().isEqualTo(arrayListOfB)
    assertThat(listOfA).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(arrayListOfA)
    assertThat(listOfA).usingRecursiveComparison().withStrictTypeChecking().isNotEqualTo(arrayListOfB)
}

class TestClassA(val name: String)

class TestClassB(val name: String)

Is there any way to achieve this?

2

There are 2 answers

0
Stefano Cordio On

Your target could be achieved with standard list assertions and a RecursiveComparator:

val listOfA = listOf(TestClassA("Name"))
val arrayListOfB = arrayListOf(TestClassB("Name"))

val configuration = RecursiveComparisonConfiguration()

configuration.strictTypeChecking(false) // default

assertThat(listOfA)
    .usingElementComparator(RecursiveComparator(configuration))
    .isEqualTo(arrayListOfB) // succeeds

configuration.strictTypeChecking(true)

assertThat(listOfA)
    .usingElementComparator(RecursiveComparator(configuration))
    .isEqualTo(arrayListOfB) // fails

Not as fluent as one would expect but it's the best option I see at the moment.

1
mkapiczy On

The response proposed by Stefano works for the given example. However, with more complex types inside the array it was failing. I am not 100% sure why but it seemed like ignoring collection order did not work.

In the end I was able to achieve my goal with a custom condition:

    private fun iterablesEqualCondition(recursiveComparisonConfiguration: RecursiveComparisonConfiguration, other: Iterable<*>): Condition<Any> {
        fun condition(actual: Any): Boolean {
            assertThat((actual as Iterable<*>).toList()).usingRecursiveComparison(recursiveComparisonConfiguration).isEqualTo(other.toList())
            return true
        }
        return Condition(::condition, "Iterables are equal condition")
    }

assertThat(listOfA).satisfies(iterablesEqualCondition(RecursiveComparisonConfiguration.builder()
            .withStrictTypeChecking(true)
            .withIgnoreCollectionOrder(true).build(), arrayListOfA))