willowtreeapps / assertk

assertions for kotlin inspired by assertj
MIT License
757 stars 84 forks source link

Issue comparing ByteArrays inside a Map #541

Open 11aescalante opened 1 month ago

11aescalante commented 1 month ago

When using isEqualTo to compare two ByteArrays it works by using contentEquals internally. But when using isEqualTo on a Collection (or any Collection assert like containsOnly), it seems that it is comparing the ByteArrays by reference. These are two examples:

val a1 = byteArrayOf(0x01, 0x02)
val a2 = byteArrayOf(0x01, 0x02)

assertThat(a1).isEqualTo(a2) //Test pass
val a1 = mapOf(1 to byteArrayOf(0x01, 0x02))
val a2 = mapOf(1 to byteArrayOf(0x01, 0x02))

assertThat(a1).isEqualTo(a2) //This fails "expected:<{1=[1, 2]}> with type:<class java.util.Collections$SingletonMap (Kotlin reflection is not available)> did not compare equal to the same type with the same string representation"
assertThat(a1).containsOnly(*a2.map { it.key to it.value }.toTypedArray()) //This also fails "expected to contain only:<{1=[1, 2]}> but was:<{1=[1, 2]}>"

As containsOnly and the other Collection variants are very useful for testing, I would expect them to compare underlying Collections with their proper comparators. Is there any chance this could be addressed in a future release?

assertk version used 0.28.1

evant commented 1 month ago

This is down to kotlin using reference equality for arrays. https://blog.jetbrains.com/kotlin/2015/09/feedback-request-limitations-on-data-classes/#appendix.-comparing-arrays

We have a special-case for asserting array equality but it's not possible to extend that for all places that arrays may be used. There has been a few asks about overriding the comparison functions used in contains* methods for various reasons so I think your second example could fall under that, but we haven't designed an api for it yet.