【问题标题】:Scala test match case classes on some fieldScala测试某些领域的匹配案例类
【发布时间】:2020-06-01 23:04:07
【问题描述】:

我有

case class Foo(field1: String, field2: String, field3: String)

expected: Seq[Foo] = Seq(...)

result: Seq[Foo] = Seq(...)

我想写一个 Scala 匹配器来比较 Seq 的元素而不考虑 field1。

因此,如果 field2 和 field3 相等,则两个元素将匹配。不考虑 Field1 值。

例子:

val expected = Seq(
  Foo(
    "f1", "f2", "f3"
  )
)

val result = Seq(
  Foo(
    "fx", "f2", "f3"
  )
)

这两个序列必须匹配。

  result should matchWithoutId(expected)

【问题讨论】:

  • 也许这表明您的模型包含不应该存在的数据?

标签: scala scalatest


【解决方案1】:

文档在Using custom Matchers,这个例子是(例如)

def matchWithoutId(expected: Foo): Matcher[Foo] = Matcher { actual =>
  MatchResult(
    actual.field2 == expected.field2 && actual.field3 == expected.field3,
    if (actual.field2 != expected.field2)
      s"field2 of $actual was not equal to that of $expected"
    else
      s"field3 of $actual was not equal to that of $expected",
    s"field2 and field3 of $actual were equal to those of $expected")
}

根据口味调整错误消息。

或另一种方法(在这种情况下可能更好):

def matchWithoutId(expected: Foo): Matcher[Foo] = have(
  'field2 (expected.field2),
  'field3 (expected.field3)
)

通常我会说应该避免使用符号来命名属性和使用反射,但这里对Foo 的更改将导致测试无法编译,因为访问了expected 的字段。

编辑:我错过了您想比较 Seq[Foo]s 而不是 Foos,所以 Mario Galic 的答案可能是您想要的答案。不过,希望这也很有用。

【讨论】:

  • 这种方案的缺点是,如果在case类中添加了一个字段,我们必须在matcher中添加条件。
  • 那么第二个方案不行,是的,但是第一个可以修改为使用actual.copy(field1 = 0) == expected.copy(field1 = 0)
【解决方案2】:

Working with "sequences" 状态

如果您想更改为元素确定容器运输的方式 键入 E,在范围内放置隐式 Equality[E] 或使用显式 DSL。

所以以下应该可以工作

(expected should contain theSameElementsAs (result)) (decided by fooEqualityWithoutId)

注意contains的用法

请注意,当您使用带有 contain 的显式 DSL 时,您需要 将整个包含表达式括在括号中

这是完整的例子

import org.scalactic._
import org.scalatest._
import org.scalatest.matchers.should.Matchers
import org.scalactic.Explicitly._

class CustomizeEqualitySeqSpec extends FlatSpec with Matchers with Explicitly {
  case class Foo(field1: String, field2: String, field3: String)
  val expected = Seq(Foo("f1", "f2", "f3"))
  val result = Seq(Foo("fx", "f2", "f3"))

  val fooEqualityWithoutId = new Equality[Foo] {
    override def areEqual(a: Foo, b: Any): Boolean = b match {
      case Foo(_, field2, field3) => a.field2 == field2 && a.field3 == field3;
      case _ => false
    }
  }

  "Sequences" should "use custom Equality[E]" in {
    (expected should contain theSameElementsAs (result)) (decided by fooEqualityWithoutId)
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2017-02-25
    • 2017-04-25
    • 2023-03-11
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多