``` I feel confused about containExactlyInAnyOrder...
# kotest
a
Copy code
I feel confused about containExactlyInAnyOrder
. I'd expect the following to pass, but it fails:
Copy code
val caseInsensitiveStringEquality: Equality<String> = object : Equality<String> {
               override fun name() = "Case Insensitive String Matcher"

               override fun verify(actual: String, expected: String): EqualityResult {
                  return if(actual.uppercase() == expected.uppercase())
                     EqualityResult.equal(actual, expected, this)
                  else
                     EqualityResult.notEqual(actual, expected, this)
               }
            }
            listOf("apple, Apple") should containExactlyInAnyOrder(listOf("APPLE", "APPLE"), caseInsensitiveStringEquality)
what am I missing?
l
Your matcher seems wrong
if(actual.uppsercase() == expected.uppercase()) EqualityResult.equal(actual, expected, this)
Shouldn't it be EqualityResult.equal(actual.uppercase(), expected.uppsercase(), this)?
a
It does not make any difference. I've modified matcher as follows
Copy code
val caseInsensitiveStringEquality: Equality<String> = object : Equality<String> {
               override fun name() = "Case Insensitive String Matcher"

               override fun verify(actual: String, expected: String): EqualityResult {
                  return if(actual.uppercase() == expected.uppercase())
                     EqualityResult.equal(actual.uppercase(), expected.uppercase(), this)
                  else
                     EqualityResult.notEqual(actual.uppercase(), expected.uppercase(), this)
               }
            }
still getting
Collection should contain ["APPLE", "APPLE"] in any order, but was ["apple, Apple"]
I know why
Copy code
fun <T, C : Collection<T>> containExactlyInAnyOrder(
   expected: C,
   verifier: Equality<T>?,
): Matcher<C?> = neverNullMatcher { actual ->

   val valueGroupedCounts: Map<T, Int> = actual.groupBy { it }.mapValues { it.value.size }
   val expectedGroupedCounts: Map<T, Int> = expected.groupBy { it }.mapValues { it.value.size }

   val passed = expectedGroupedCounts.size == valueGroupedCounts.size && // this line is wrong
here we are matching 1 with 2
because
["APPLE", "APPLE"]
has size of 1 after grouping