I was just surprised by a failing test assert (using kotlin.test here):
data class MyType {
var values : MutableSet<OtherType> = mutableSetOf()
}
data class OtherType(val value: String) {}
assertEquals(setOf(OtherType(myValue)), myObject.values)
The error looks like this:
expected: java.util.Collections$SingletonSet<[OtherType(value=myvalue)]> but was: java.util.LinkedHashSet<[OtherType(value=myvalue)]>
Clearly, the test should have been successful: I only care about value equality and not at all about which set implementation is used.
How do I express this best in Kotlin?
Ideas
Use Guava: assertTrue(Sets.symmetricDifference(setOf(OtherType(myValue)), myObject.values).isEmpty())
rather lengthy, though, and un-mathy colleagues might not understand it
Create a new assertion function like assertEqualContent for comparing sets by content.
Re-define == on sets (or all collections?): it should ignore the concrete type of the set itself.
For now, I went with 2 implemented using 1. A solution without Guava would be nice, though.
Ahh… that is what I get for not actually running the MWE. My bad; the setup looked too obvious. Should’ve learned that lesson a while ago. :'D
Here’s an actual MWE; it’s not about the sets at all:
data class OtherType(val value: String) {
// Set by GORM
var id: Long? = null
var version: Int? = null
override fun equals(other: Any?): Boolean {
return when (other) {
!is OtherType -> false
id == other.id && value == other.value -> true
else -> false
}
}
}
fun main(args: Array<String>) {
val myValue = "test"
println(OtherType(myValue) == OtherType(myValue))
}
Now that I actually looked at OtherType.equals, the problem is apparent – if you’ve seen Kotlin Puzzlers 2018 (code). It only looks correct (might be a Swift-ism). With
override fun equals(other: Any?): Boolean {
return when (other) {
is OtherType -> id == other.id && value == other.value
else -> false
}
}
everything works as expected, including set comparison.
Thanks for your help! (And for submitting that puzzler to Anton!)