Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala、Specs2和共享状态_Scala_Testing_Specs2 - Fatal编程技术网

Scala、Specs2和共享状态

Scala、Specs2和共享状态,scala,testing,specs2,Scala,Testing,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.

我正在写一些规范;这看起来像:

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]
是共享的

  • 一种解决方案是在每次测试之前使它们顺序排列并重置模拟,但这看起来很奇怪,正如文档中关于“默认并行”的内容所述:
当一个例子的结果不应该受到其他人的影响时,它鼓励写独立的例子

  • 另一种方法是将
    val
    移动到测试本身。但是,虽然我应该能够减少重复,但这看起来仍然像一个奇怪的结构。并且看起来
    主题
    是有状态的,而它不应该是有状态的

  • 我还可以尝试使用不太严格的方法,通过使用
    验证是否存在atLestOne(依赖项)。something()
    但是:

  • 这并不验证该方法是否在该特定测试用例中被调用,并且
  • 参数捕获和验证是痛苦的
所以我的问题是:

如何在mock上创建具有详细验证的可读测试

非常感谢

可以像这样为每个测试提供新的状态

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()
    }
  }
}

谢谢,我用一个私有方法做了一个等价的操作,该方法返回一个
元组[Subject,Dependency]
,但这更简洁。我还提到了
isolated
关键字,您是否有反对或赞成该关键字的论点?我会避免使用
isolated
,因为我对它在可变规格下的实现不是很有信心。它需要做各种各样的扭曲才能到达那里。还要注意的是,
Scope
依赖于
DelayedInit
功能,该功能不保证保留在Scala 3中。因此,如果您想安全起见:
val-dependency=mock[dependency];val subject=新组件(..)
在每个示例中。。。