ScalaTest 深度比较最佳实践

Ian*_*Ian 5 scala scalatest

我正在尝试为返回包含数组的类的元组的函数编写单元测试。

由于数组的原因,简单assert(out === expectedOut)out should be(expectedOut)不比较 LHS 和 RHS 上的类的内容。ScalaTest 中有没有一种巧妙的方法可以做到这一点?

我看过自定义匹配器,但我不确定这是否是我想做的事情的最佳方法。因此,任何来自专家经验的信息将不胜感激。

编辑:这是一个似乎并非如此的情况:

object Utils {
  case class Product(id: Int, prices: Array[Int])


  def getProductInfo(id: Int, prices: Array[Int]): Option[Product] = {
    val sortedPrices = prices.sortWith(_ < _)
    Some(Product(id, sortedPrices))
  }
}

---

import org.scalatest._
import Utils._

class DataProcessorSpec extends FlatSpec with Matchers with OptionValues {
  val id = 12345
  val priceList = Array(10,20,30)

  val prod = Utils.getProductInfo(id, priceList)
  val expectedProd = Some(Utils.Product(id, priceList))

  "A DataProcessorSpec" should "return the correct product information" in {
     prod should be(expectedProd)
  }
}
Run Code Online (Sandbox Code Playgroud)

sortWith据我所知,测试失败是因为这会导致创建一个新数组,从而指向不同的内存位置。

Tza*_*har 7

更新:通过代码示例,这更清楚:

比较失败,因为shoud be使用案例类的equals函数来执行比较,并且案例类不会“深入”比较数组 - 这意味着,正如您所怀疑的那样,不同的实例将不相等(请参阅此处的更多信息)。

解决方法

  1. 分别验证案例类的每个“部分”的相等性:

    prod.get.prices should be(expectedProd.get.prices)
    prod.get.id should be(expectedProd.get.id)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果 usingArray不是必须的,你可以将 case 类更改为 use Seq[Int],这将使测试通过,因为 aSeq的实现equals “深”的

比较数组

当“单独”比较时,数组将按预期(“深度”)通过 Matchers' 进行比较should be

arr1 should be(arr2) // true if contents is the same
Run Code Online (Sandbox Code Playgroud)

如果您只是想比较内容,而不验证它out确实是一个Array,您可以使用theSameElementsInOrderAs

arr1 should contain theSameElementsInOrderAs arr2
Run Code Online (Sandbox Code Playgroud)