如何为组合集合定义“LoneElement”和“Emptiness”?

How can I define `LoneElement` and `Emptiness` for composed collections?

我有一个案例 class,它是一个集合的简单包装器:

final case class Foo(foos: Seq[Int])

并且在我的测试中,我想对 Foo#foos 的空虚和孤立元素做出断言。我目前通过直接访问 Foo#foos 来规避问题:

foo.foos shouldBe empty

foo.foos.loneElement should===(1)

这有效,但破坏了封装。

我查看了最大规模的文档,但没有找到在同伴之外定义这些运算符的方法。

如何定义它们?在测试中内联它们的奖励积分。

定义一些处理 Foo 的隐含函数(在 test 目录中,而不是在 main 源代码树中):

import org.scalatest.enablers.Emptiness

trait FooImplicits {

  case class FooLoneElementWrapper(wrapped: Foo) {
    def loneElement: Int = {
      assert(wrapped.foos.size == 1)
      wrapped.foos(0)
    }
  }
  implicit def fooCanHazLoneElement(foo: Foo) = FooLoneElementWrapper(foo)
  implicit object FooEmptiness extends Emptiness[Foo] {
    def isEmpty(foo: Foo) = foo.foos.isEmpty
  }

}

现在只需将特征 FooImplicits 混合到 FlatSpec 您想要使用它的地方:

import org.scalatest._

class FooSpec extends FlatSpec with Matchers with FooImplicits {

  "Foo" should "be empty when it's empty" in {
    Foo(Seq()) shouldBe empty
  }

  it should "have loneElements" in {
    val x = Foo(Seq(1))
    x.loneElement should equal (1)
  }
}

利润:

[info] Foo
[info] - should be empty when it's empty
[info] - should have loneElements

请注意,FooImplicits 可以在与 main 树中的 Foo 相同的 package 中定义,即使它们在完全不同的 [=14] 中=]-源代码树。这样,它可以访问 Foo.

的包可见成员