Case class equals with list of byte array
Asked Answered
H

2

5

I am trying to use the should matchers on a case class

case class ListOfByteArrayCaseConfig(

  @BeanProperty 
  permissions: java.util.List[Array[Byte]]

)

With the following test case

val orig = ListOfByteArrayCaseConfig(List(Array[Byte](10, 20, 30)))
val orig2 = ListOfByteArrayCaseConfig(List(Array[Byte](10, 20, 30)))

orig2 should be === orig

Obviously this would fail because the two byte arrays are not equal reference wise. What I want to do is somehow make this work without changing the test case code and still keeping the case class.

Is it even possible? (like adding a custom equals method to the case class?)

Hanger answered 22/10, 2012 at 21:4 Comment(1)
You are using ScalaTest or Specs2?Courbet
H
2

I found the solution. Apparently I can override the equals method in a case class

Scala: Ignore case class field for equals/hascode?

Though it gets rid of the reason for using case classes in the first place which is to simplify data objects.

case class ListOfByteArrayCaseConfig(

  @BeanProperty 
  permissions: java.util.List[Array[Byte]]

) {

  override def equals(arg: Any): Boolean = {

    val obj = arg.asInstanceOf[ListOfByteArrayCaseConfig]
    var i: Int = 0
    for (i <- 0 until permissions.size()) {
      if (!util.Arrays.equals(permissions.get(i), obj.permissions.get(i))) {
        return false
      }
    }
    return true
  }
}
Hanger answered 22/10, 2012 at 21:21 Comment(3)
+1, but you should not assume that object passed to equals() is of ListOfByteArrayCaseConfig type. Moreover, consider using pattern matching instead of downcasting.Halfmoon
You had better override hashCode also if you plan on using this with sets or maps (or just want hashCode and equals to be consistent).Slovenia
True, I just wanted a quick and dirty class to be used for testing, but I agree it needs a hashCode and a proper equals implementation. At the very least this shows what can be done.Hanger
H
0

Linking this here as well.

Seems like it is a known issue - https://github.com/scalatest/scalatest/issues/491.

I worked around in an effective but maybe ugly way

  case class MyCaseClass(
    bytes: Array[Byte]
  )

  implicit val customEquality: Equality[MyCaseClass] = (a: MyCaseClass, b: Any) => b match {
    case exp: MyCaseClass =>
      exp.bytes.toSeq == a.bytes.toSeq && exp.copy(bytes = Array.empty) == a.copy(bytes = Array.empty)
    case _ => false
  }
Hellenic answered 10/6 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.