Scalatest断言失败:内容一致的IdToLabel对象不匹配
Scala单元测试中Array字段导致断言失败的问题解决
问题根源
你遇到的问题核心在于Scala的Array类型基于Java数组实现,它的equals方法比较的是对象引用而非内容。虽然两个数组的toString输出看起来完全一致,但只要它们是不同的数组实例,equals就会返回false。
而你的IdToLabel是case class,它默认的equals方法会逐成员进行比较,当比较到customLabels: Option[Array[String]]时,就会因为数组的引用不等导致整个IdToLabel对象的equals结果为false,最终让ComputationResult的断言失败。
解决方案
1. 替换Array为Scala原生集合(推荐)
把Array[String]换成Scala的List[String]或Seq[String],这些集合类型的equals方法是基于内容比较的,case class会自动使用正确的逻辑进行对象相等性判断:
final case class IdToLabel(totalLabel: Option[String], buyLabels: Option[Map[String, UUID]], customLabels: Option[List[String]]) // 或Seq[String]
2. 自定义IdToLabel的equals和hashCode方法
如果必须保留Array类型,可以重写equals方法来手动比较数组内容,同时也要重写hashCode保证一致性:
final case class IdToLabel(totalLabel: Option[String], buyLabels: Option[Map[String, UUID]], customLabels: Option[Array[String]]) { override def equals(other: Any): Boolean = other match { case that: IdToLabel => totalLabel == that.totalLabel && buyLabels == that.buyLabels && // 比较两个Option[Array]的内容 (customLabels, that.customLabels) match { case (Some(arr1), Some(arr2)) => java.util.Arrays.equals(arr1, arr2) case (None, None) => true case _ => false } case _ => false } override def hashCode(): Int = { val prime = 31 var result = totalLabel.hashCode() result = prime * result + buyLabels.hashCode() result = prime * result + customLabels.map(java.util.Arrays.hashCode).getOrElse(0) result } }
3. 测试中单独比较数组内容
如果不想修改类定义,可以在测试断言时,针对数组字段单独检查内容是否一致(以ScalaTest为例):
// 分别比较每个字段 assert(expected.idToLabel.totalLabel == actual.idToLabel.totalLabel) assert(expected.idToLabel.buyLabels == actual.idToLabel.buyLabels) // 检查数组内容是否相同 val expectedCustom = expected.idToLabel.customLabels.getOrElse(Array.empty[String]) val actualCustom = actual.idToLabel.customLabels.getOrElse(Array.empty[String]) assert(expectedCustom.sameElements(actualCustom))
内容的提问来源于stack exchange,提问作者firas_frikha
相关产品推荐
相关产品推荐

