我正在编写一些 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()
验证来尝试使用不太严格的方法,但是:- 这不能验证该方法在此特定的测试案例中被调用,
- 论点捕获和验证是痛苦的。
所以我的问题是:
我如何创建可读的测试,并在模拟上进行详细验证。
非常感谢。
范围可以为每个测试提供新的状态,例如
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()
}
}
}