Scala,Specs2和共享状态



我正在编写一些 specs2 规格;看起来像:

class ComponentSpecification extends Specification with Mockito {
  private val dependency = mock[Dependency]
  private val subject = new Component(..)
  "methodOne" should {
    "handle happy path" in {
       val result = subject.methodOne("Param1", 42)
       result must ...
       there was one(dependency).something()
    }
    "deal with border case" in {
       val result = subject.methodOne("", -1)
       result must ...
       there was one(dependency).something()
    }
  }
}

但是,这些测试失败了,因为共享了mock[Dependency]

  • 一种解决方案是使它们顺序结束并在每个测试之前重置模拟,但是这看起来很奇怪,并且按照Doc中写入"默认情况下的平行" ::

当给定示例的结果不应受到他人的影响时,它鼓励写独立的例子

  • 另一个是将val移至测试本身。但是,尽管我应该能够减少重复,但看起来仍然像是一个奇怪的结构。看起来subject是陈述的,而不应。

  • 我也可以通过使用there was atLestOne(dependency).something()验证来尝试使用不太严格的方法,但是:

    1. 这不能验证该方法在此特定的测试案例中被调用,
    2. 论点捕获和验证是痛苦的。

所以我的问题是:

我如何创建可读的测试,并在模拟上进行详细验证。

非常感谢。

范围可以为每个测试提供新的状态,例如

class ComponentSpecification extends mutable.Specification with Mockito {
  trait FooScope extends Scope {
    val dependency = mock[Dependency]
    val subject = new Component(dependency)
  }
  "methodOne" should {
    "handle happy path" in new FooScope {
      val result = subject.methodOne("Param1", 42)
      there was one(dependency).something()
    }
    "deal with border case" in new FooScope {
      val result = subject.methodOne("", -1)
      there was one(dependency).something()
    }
  }
}

在每个测试之前都不需要重置模拟的地方。

我要接受@mario Galic的答案。但是,关于@Eric(Specs2的作者(的评论,我以一种方法结束,该方法以预期的方式创建上下文,但可以消除重复。通过使用模式匹配,我提取有趣的部分:

class ComponentSpecification extends mutable.Specification with Mockito {
  def givenOneCallToMethodOneWithDependency(s:String, i:Int):(Result, Dependency) = {
    val dependency = mock[Dependency]
    val subject = new Component(dependency)
    val result = subject.methodOne(s, i)
    (result, dependency)
  }
  "methodOne" should {
    "handle happy path" in new FooScope {
      val (result, dependency) = givenOneCallToMethodOneWithDependency("Param1", 42)
      there was one(dependency).something()
    }
    "deal with border case" in new FooScope {
      val (result, dependency) = givenOneCallToMethodOneWithDependency("", -1)
      there was one(dependency).something()
    }
  }
}

最新更新