当 Scala 案例类包含内部数组时,Scala 案例类的相等性在 junit assertEquals 中不起作用

Equality of Scala case class does not work in junit assertEquals when it contains an inner Array

提问人:Cyrus 提问时间:11/15/2019 最后编辑:Ivan StanislavciucCyrus 更新时间:11/17/2019 访问量:437

问:

我在 scala 中尝试为此运行单元测试,但同时将 foo 元素(实际和预期)存储在数组中。 所以最后一行是使用 .case class foo(a: Array[String], b: Map[String,Any])assertEqualsassertEquals(expected.deep, actual.deep)

映射 b 显示正确,但 assertEquals 正在尝试匹配数组 a 的哈希码而不是内容。错误是 get 是这样的:Array(foo([Ljava.lang.string@235543a70,Map("bar" -> "bar")))

整体代码如下所示

  case class Foo(a: Array[String], b: Map[String, Any])

  val foo = Foo(Array("1"), Map("ss" -> 1))
  val foo2 = Foo(Array("1"), Map("ss" -> 1))

  org.junit.Assert.assertEquals(Array(foo).deep, Array(foo2).deep)

你建议如何做到这一点?

Scala JUnit 等于 Equality 案例类

评论

0赞 Thilo 11/17/2019
Java 数组未正确实现相等性检查。请改用 。Seq

答:

2赞 Ivan Stanislavciuc 11/15/2019 #1

scala 中的 case 类有自己的方法,不应该被覆盖。此实现检查内容的相等性。但它依赖于基于“内容”的 case 类中使用的类型的实现。hashCodeequalshashCodeequals

不幸的是,情况并非如此,这意味着不能使用默认方法按内容检查数组。Arraysequals

最简单的解决方案是使用基于内容检查相等性的数据集合,例如 .Seq

  case class Foo(a: Seq[String], b: Map[String, Any])

  val foo = Foo(Seq("1"), Map("ss" -> 1))
  val foo2 = Foo(Seq("1"), Map("ss" -> 1))

  org.junit.Assert.assertEquals(foo, foo2)

在这种情况下,调用对您没有帮助,因为它仅扫描和转换嵌套。deepArray

  println(Array(foo, Array("should be converted and printed")))
  println(Array(foo, Array("should be converted and printed")).deep)

生产

[Ljava.lang.Object;@188715b5
Array(Foo([Ljava.lang.String;@6eda5c9,Map(ss -> 1)), Array(should be converted and printed))